我的程序有以下要求:如果给出命令行参数,将其解释为文件名并从该文件读取输入。否则,改为从 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); 
} 


评论关闭
IT序号网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!