Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 将输入读取到数组中会导致分段冲突_C_Arrays_String_File_Dynamic Memory Allocation - Fatal编程技术网

C 将输入读取到数组中会导致分段冲突

C 将输入读取到数组中会导致分段冲突,c,arrays,string,file,dynamic-memory-allocation,C,Arrays,String,File,Dynamic Memory Allocation,我的程序有以下要求:如果给定了命令行参数,则将其解释为文件名并从该文件读取输入。否则,从stdin读取输入。因为我以后需要输入,所以我想将其保存到一个数组中。因为任何非ASCII字符都将被忽略,所以我决定逐个字符地处理输入字符。这是我的代码: #include <string.h> #include <stdio.h> #include <stdlib.h> #include <ctype.h> #define MAX_WORDS 999 #de

我的程序有以下要求:如果给定了命令行参数,则将其解释为文件名并从该文件读取输入。否则,从
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]);
}
#包括
#包括
#包括
#包括
#定义最大字数999
#定义最大单词长度50
typedef结构数据{
字符字[MAX_words][MAX_words_LENGTH+1];
国际货币基金组织;
}数据;
数据*数据;
int main(int argc,字符**argv){
数据=malloc(数据大小);
文件*填充;
如果(argcwords[wordindex][charindex]='\0';
wordindex++;
charindex=0;
如果(单词索引>=MAX|u单词| c==EOF)
打破
继续;
}
如果(!isascii(c))
继续;
数据->单词[wordindex][charindex]=toupper(c);
charindex++;
if(charindex>=最大字长){
wordindex++;
charindex=0;
如果(单词索引>=最大单词数)
打破
}
}
如果(argc==2)fclose(infle);
数据->numwords=wordindex-1;
//检查是否一切正常
printf(“=========================\n读取%d个字:\n”,数据->多个字);
对于(int i=0;inumwords;i++)
printf(“%d%s\n”),(int)strlen(数据->单词[i]),数据->单词[i]);
}
如果我通过stdin输入,一切都正常,但如果我试图从文本文件读取输入,程序会出错。如果文本文件只包含一行文本,似乎可以工作,但如果有两行或更多行文本,则会崩溃。我是C初学者,我看不到从stdin或文件读取之间有任何区别,因此我有n你知道为什么会这样。有人能给我点化一下吗

Data* data;
data= malloc(sizeof data);
分配字节以适应
数据
的大小,
数据
只是指向
数据
的指针,而不是
数据
本身。指针为4/8字节,具体取决于是否使用32/64位平台

在这里分配很少的内存会导致很快写入无效内存,并由此调用臭名昭著的未定义行为。从现在起,任何事情都可能发生,从崩溃到零

如果您希望保存
数据的字节数
,您希望这样分配

data = malloc(sizeof (Data));
data = malloc(sizeof *data);
这样更好

data = malloc(sizeof (Data));
data = malloc(sizeof *data);

还应测试相关系统调用的结果,并且
malloc()
可能会失败:

if (NULL == data)
{
  perror("malloc() failed");
  exit(EXIT_FAILURE);
}

与您的问题无关,但是如果您只是分配一个结构,为什么要动态分配单个结构?或者通常分配在编译时决定的多个结构化结构?为什么不使用结构的数组?如果您将数组作为全局变量,那么它将不会占用堆栈空间,如果这正是您所担心的。还请注意,这并不重要不要返回
char
。这实际上非常重要。@JoachimPileborg我没有特别的理由在那里使用malloc,只是因为我是noob:)无论如何,我不明白如果
fgetc
返回int为什么重要,我刚刚检查过,比较
c==EOF
的效果很好。
fgetc
EOF
的问题是
EOF
-1
,和所有整数文本一样
-1
int
,它的值(在一个双补32位机器上)是
0xffffffff
char
通常是一个字节,八位,然后负一位的值为
0xff
,或者是32位的值
0x000000ff
。由于
char
可能是
unsigned
(标准中没有定义
char
的有符号性),您可以将
0x000000ff
0xffffffff
进行比较,这将不会产生正确的结果。@JoachimPileborg这是一个很好的解释,谢谢。我马上去修。你说得对,把代码改成
sizeof*data
行了。我很想理解为什么我的代码在阅读标准文本时没有崩溃,如果你能解释一下,那就太好了。@rawing:我刚刚添加了一些关于未定义行为的词汇。哦,那只是巧合,或多或少?我猜我读得太多了。@rawing:我会说是运气不好。看看Valgrind来测试这些问题。在C中运行的代码不一定是正确的代码@拉温