gets在vs2015里老报错,用gets_s或getline总是会跳过第一个字符串的输入

C++语言 码拜 9年前 (2016-04-01) 1228次浏览
本人在vs2015定义了一个结构体,结构体成员有几个字符串,本人在对结构体进行输入操作时,总是出问题,用C语言标准的字符串输入函数gets不是提示不安全就是提示不认识(stdio.h头文件包了就提示不安全,让用gets_s;去掉安全检查,又提示gets不认识,感觉编译器故意不让你用gets)。改用用gets_s或getline,虽然编译器不报错,但是程序运行出错,对结构体输入时,第一个字符串变量总是会跳过,得不到输入。为这破东西,整了一个月都没解决,崩溃死了,问一下谁有好的办法能解决?

// 9_6.cpp : Defines the entry point for the console application.
//
//#define _CRT_SECURE_NO_WARNINGS
#include "stdafx.h"
#include <stdio.h>
//#include <cstdio>
#include <stdlib.h>
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
#define MAX_COMMODITY_NUM 100
#define COM_PERO_LEN 30
struct _comStrc
{
	char sNo[COM_PERO_LEN];
	char sType[COM_PERO_LEN];
	char sWhereCounter[COM_PERO_LEN];
	float price;
	int iTotal;
	long lDate;
};
_comStrc InputCommInfo()
{
	_comStrc m_comm;
	fflush(stdin);
	cout << setw(45) << "商品信息输入:\n";
	cout << setw(30) << "商品编号:";
	//gets(m_comm.sNo);
	gets_s(m_comm.sNo);//安全你妈逼!非要用这破逼东西才编译通过
//	getline(cin, m_comm.sNo);
	cout << setw(30) << "商品类型:";
	gets_s(m_comm.sType);
	cout << setw(30) << "存储柜台:";
	gets_s(m_comm.sWhereCounter);
	cout << setw(30) << "商品单价:";
	cin >> m_comm.price;
	cout << setw(30) << "商品数量:";
	cin >> m_comm.iTotal;
	cout << setw(30) << "生产日期:";
	cin >> m_comm.lDate;
	return m_comm;
}
void WriteCommodityData(char *fname,_comStrc *com,int iLen)
{
	FILE *fp;
	if (NULL==(fp=fopen(fname,"ab")))//可写二进制数据
	{
		printf("can not open file!\n");
		exit(1);
	}
	fwrite(&iLen,sizeof(int),1,fp);
	if (ferror(fp))
	{
		cout << "写入商品数量时出错,请检查一下,O(∩_∩)O谢谢!\n";
		fclose(fp);
		return;
	}
	fwrite(com, sizeof(_comStrc), iLen, fp);//一次写入多个
	fclose(fp);
}
void ReadCommodity(char *fname,_comStrc *com,int &iLen)
{
	FILE *fp;
	if (NULL==(fp=fopen(fname,"rb")))
	{
		printf("can not open file!\n");
		exit(1);
	}
	if (feof(fp))
	{
		cout << "抱歉,文件是空的!";
		return;
	}
	fread(&iLen,sizeof(int),1,fp);
	printf("读出的商品个数:%d\n", iLen);
	if (ferror(fp))
	{
		printf("从文件中读商品数量时出错!\n");
		fclose(fp);
		return;
	}
	if (fread(com,sizeof(_comStrc),iLen,fp) != iLen)
	{
		printf("read file error!");
		fclose(fp);
		exit(1);
	}
	cout.setf(ios::left);
	printf("读出的商品信息如下:\n");
	cout << setw(10) << "商品编号" << setw(10) << "商品类型" << setw(10) << "存储柜台" << setw(10) << "商品单价" << setw(10) << "商品数量" << setw(10) << "生产日期" << endl;
	for (size_t i = 0; i < iLen; i++)
	{
		cout << setw(10) << com[i].sNo << setw(10) << com[i].sType << setw(10) << com[i].sWhereCounter << setw(10) << com[i].price << setw(10) << com[i].iTotal << setw(10) << com[i].lDate << endl;
	}
	cout.unsetf(ios::left);
	fclose(fp);
}
#define COMM_LEN 3
int main()
{
	int iLen = 0;
	char filename[20] = { 0 };
	_comStrc m_comm[COMM_LEN], m_rcomm[COMM_LEN];
	printf("请输入要写入商品信息的文件名:\n");
	scanf("%s", filename);
	printf("请输入%d个商品的信息:\n",COMM_LEN);
	for (size_t i = 0; i < COMM_LEN; i++)
	{
		m_comm[i] = InputCommInfo();
		/*int iRet = sizeof(m_comm[i]);//for test
		iRet = sizeof(_comStrc);
		iRet = 0;*/
	}
	WriteCommodityData(filename, m_comm, COMM_LEN);
	ReadCommodity(filename, m_rcomm, iLen);
    return 0;
}

gets在vs2015里老报错,用gets_s或getline总是会跳过第一个字符串的输入

解决方案

10

参考MSDN:https://msdn.microsoft.com/en-us/library/5b5x9wc7.aspx
你商品编号输入了几位?
改成

gets_s(m_comm.sNo, COM_PERO_LEN );

试试

5

char sWhereCounter[COM_PERO_LEN];
fgets(sWhereCounter,COM_PERO_LEN,stdin);
if ("\n"==sWhereCounter[strlen(sWhereCounter)-1]) sWhereCounter[strlen(sWhereCounter)-1]=0;

5

引用:
Quote: 引用:
char sWhereCounter[COM_PERO_LEN];
fgets(sWhereCounter,COM_PERO_LEN,stdin);
if ("\n"==sWhereCounter[strlen(sWhereCounter)-1]) sWhereCounter[strlen(sWhereCounter)-1]=0;

谢谢赵老师的回答,本人按照您指点的对结构体的第一个字符串输入用死循环做了一个有效性验证,试了一下,现在第一个字符串变量可以在控制台得到输入,但是结构体的后面几个变量都得不到输入,具体现象是,可以在控制台输入,但是什么也不显示,在路径下也看不到产生的文件。本人修改代码如下:

	do 
	{
		fgets(m_comm.sNo, COM_PERO_LEN, stdin);
		if ("\n" == m_comm.sNo[strlen(m_comm.sNo) - 1])
		{
			m_comm.sNo[strlen(m_comm.sNo) - 1] = 0;
		}
		else
		{
			break;
		}
	} while (0 != m_comm.sNo[strlen(m_comm.sNo) - 1] );

gets在vs2015里老报错,用gets_s或getline总是会跳过第一个字符串的输入
本人尝试把结构体的全部字符串变量都做这样修改,

	do 
	{
		fgets(m_comm.sNo, COM_PERO_LEN, stdin);
		if ("\n" == m_comm.sNo[strlen(m_comm.sNo) - 1])
		{
			m_comm.sNo[strlen(m_comm.sNo) - 1] = 0;
		}
		else
		{
			break;
		}
	} while (0 != m_comm.sNo[strlen(m_comm.sNo) - 1] );
//	getline(cin, m_comm.sNo);
	cout << setw(30) << "商品类型:";
	//gets_s(m_comm.sType,COM_PERO_LEN);
	do
	{
		fgets(m_comm.sType, COM_PERO_LEN, stdin);
		if ("\n" == m_comm.sType[strlen(m_comm.sType) - 1])
		{
			m_comm.sType[strlen(m_comm.sType) - 1] = 0;
		}
		else
		{
			break;
		}
	} while (0 != m_comm.sType[strlen(m_comm.sType) - 1]);
	cout << setw(30) << "存储柜台:";
	//gets_s(m_comm.sWhereCounter,COM_PERO_LEN);
	do
	{
		fgets(m_comm.sWhereCounter, COM_PERO_LEN, stdin);
		if ("\n" == m_comm.sWhereCounter[strlen(m_comm.sWhereCounter) - 1])
		{
			m_comm.sWhereCounter[strlen(m_comm.sWhereCounter) - 1] = 0;
		}
		else
		{
			break;
		}
	} while (0 != m_comm.sWhereCounter[strlen(m_comm.sWhereCounter) - 1]);

结果还是一样

VS2015已经彻底放弃gets了
http://blog.csdn.net/hgj125073/article/details/8282883

5

引用:
Quote: 引用:
Quote: 引用:
Quote: 引用:

你的InputCommInfo就不对,使用了浅拷贝,返回了局部变量的地址,所以不要怪get_s函数啦,get_s函数是无辜的

谢谢你的回答,但是假如真是浅拷贝引起的,应该都得不到输入( ⊙ o ⊙ )啊!为什么本人总是结构体的第一个成员    char sNo[COM_PERO_LEN];得不到输入,而后面的5个成员都能正确得到输入呢?
char sType[COM_PERO_LEN];
char sWhereCounter[COM_PERO_LEN];
float price;
int iTotal;
long lDate;

涉及到内存管理的问题,具体的实现不太明白。
下面的代码应该可以运行

struct _comStrc
{
    _comStrc(const _comStrc &c)
    {
         strcpy(c.sNo,sNo);
         strcpy(c.sType,sType);
         strcpy(c.sWhereCounter,sWhereCounter);
         c.price=price;
         c.iTotal=iTotal;
         c.lDate=lDate;
     }
    char sNo[COM_PERO_LEN];
    char sType[COM_PERO_LEN];
    char sWhereCounter[COM_PERO_LEN];
    float price;
    int iTotal;
    long lDate;
};

你好,本人按你说的,修改结构体定义后,还没编译就报错,提示const类型不兼容
1>– Build started: Project: 9_6, Configuration: Debug Win32 —
1>  9_6.cpp
1>d:\vs2015exercise\文件操作\9_6\9_6\9_6.cpp(27): error C2664: “char *strcpy(char *,const char *)”: cannot convert argument 1 from “const char [30]” to “char *”
1>  d:\vs2015exercise\文件操作\9_6\9_6\9_6.cpp(27): note: Conversion loses qualifiers
1>d:\vs2015exercise\文件操作\9_6\9_6\9_6.cpp(28): error C2664: “char *strcpy(char *,const char *)”: cannot convert argument 1 from “const char [30]” to “char *”
1>  d:\vs2015exercise\文件操作\9_6\9_6\9_6.cpp(28): note: Conversion loses qualifiers
1>d:\vs2015exercise\文件操作\9_6\9_6\9_6.cpp(29): error C2664: “char *strcpy(char *,const char *)”: cannot convert argument 1 from “const char [30]” to “char *”
1>  d:\vs2015exercise\文件操作\9_6\9_6\9_6.cpp(29): note: Conversion loses qualifiers
1>d:\vs2015exercise\文件操作\9_6\9_6\9_6.cpp(30): error C3490: “price” cannot be modified because it is being accessed through a const object
1>d:\vs2015exercise\文件操作\9_6\9_6\9_6.cpp(31): error C3490: “iTotal” cannot be modified because it is being accessed through a const object
1>d:\vs2015exercise\文件操作\9_6\9_6\9_6.cpp(32): error C3490: “lDate” cannot be modified because it is being accessed through a const object
1>d:\vs2015exercise\文件操作\9_6\9_6\9_6.cpp(43): error C2512: “_comStrc”: no appropriate default constructor available
1>  d:\vs2015exercise\文件操作\9_6\9_6\9_6.cpp(24): note: see declaration of “_comStrc”
1>d:\vs2015exercise\文件操作\9_6\9_6\9_6.cpp(165): error C2512: “_comStrc”: no appropriate default constructor available
1>  d:\vs2015exercise\文件操作\9_6\9_6\9_6.cpp(24): note: see declaration of “_comStrc”
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
gets在vs2015里老报错,用gets_s或getline总是会跳过第一个字符串的输入

好像写错了。

struct _comStrc
{
    _comStrc() {}
    _comStrc(const _comStrc &c)
    {
         strcpy(sNo,c.sNo);
         strcpy(sType,c.sType);
         strcpy(sWhereCounter,c.sWhereCounter);
         price=c.price;
         iTotal=c.iTotal;
         lDate=c.lDate;
     }
    char sNo[COM_PERO_LEN];
    char sType[COM_PERO_LEN];
    char sWhereCounter[COM_PERO_LEN];
    float price;
    int iTotal;
    long lDate;
};

CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明gets在vs2015里老报错,用gets_s或getline总是会跳过第一个字符串的输入
喜欢 (0)
[1034331897@qq.com]
分享 (0)