我的程序有以下要求:如果给出命令行参数,将其解释为文件名并从该文件读取输入。否则,改为从 stdin
读取输入。因为我稍后需要输入,所以我想将它保存到一个数组中。因为要忽略任何非 ASCII 字符,所以我决定逐个字符地处理输入。这是我的代码:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define MAX_WORDS 999
#define MAX_WORD_LENGTH 50
typedef struct Data{
char words[MAX_WORDS][MAX_WORD_LENGTH+1];
int numwords;
} Data;
Data* data;
int main(int argc, char** argv){
data= malloc(sizeof data);
FILE* infile;
if(argc<=1){//if no arguments, read words from stdin
infile= stdin;
}else if(argc==2){//read words from file
infile= fopen(argv[1], "r");
if(infile==NULL){
printf("failed to open word file");
return 1;
}
}
char c;
int wordindex= 0;
int charindex= 0;
while(1){//read input character by character, only accepting ASCII characters
c= fgetc(infile);
if(c=='\n' || c==EOF){
data->words[wordindex][charindex]= '\0';
wordindex++;
charindex= 0;
if(wordindex>=MAX_WORDS || c==EOF)
break;
continue;
}
if(!isascii(c))
continue;
data->words[wordindex][charindex]= toupper(c);
charindex++;
if(charindex>=MAX_WORD_LENGTH){
wordindex++;
charindex= 0;
if(wordindex>=MAX_WORDS)
break;
}
}
if(argc==2) fclose(infile);
data->numwords= wordindex-1;
//check if everything worked as intended
printf("==================\n%d word(s) read:\n", data->numwords);
for (int i = 0; i < data->numwords; i++)
printf("%d %s\n", (int)strlen(data->words[i]), data->words[i]);
}
如果我通过标准输入输入,一切正常,但如果我试图从文本文件中读取输入,程序就会出现段错误。如果文本文件只包含一行文本,它似乎可以工作,但如果有两行或更多,它就会崩溃。我是 C 的初学者,我看不出从 stdin 或文件中读取有什么区别,所以我不知道为什么会这样。谁能赐教一下?
请您参考如下方法:
这个
Data* data;
data= malloc(sizeof data);
分配字节以适应data
的大小,data
“只是”指向Data
的指针,而不是Data
本身。一个指针是 4/8 字节,取决于是否是 32/64 位平台。
在这里分配很少的内存会导致很快写入无效内存,并由此调用臭名昭著的未定义行为。从这一刻起,任何事情都可能发生,从崩溃到什么都没有。
如果你想要字节数来保存你想要这样分配的Data
data = malloc(sizeof (Data));
这样更好
data = malloc(sizeof *data);
还应该测试相关系统调用的结果,malloc()
也可能会失败:
if (NULL == data)
{
perror("malloc() failed");
exit(EXIT_FAILURE);
}