我最近在c程序中遇到了非常奇怪的行为。我掏出了大部分代码只是为了找出问题发生在你们身上的地方。
程序在当前状态下的目的是从txt文件中读取作业并将内容打印到屏幕上。这是:
#include <stdio.h>
int main(){
char* user;
char process;
int arrival;
int duration;
scanf("%*[^\n]"); //skipping header in the file.
while(!feof(stdin))
{
scanf("%s\t%c\t%d\t%d\n", user, &process, &arrival, &duration);
printf("%s\t%c\t%d\t%d\n", user, process, arrival, duration);
}
int x[5]; //<----- Causing the weird behaviour
}
我输入的文件是:
User Process Arrival Duration
Jim A 2 5
Mary B 2 3
Sue D 5 5
Mary C 6 2
我遇到的问题是每当我声明int x数组时,无论它是在我的代码的底部还是顶部,while循环进入无限循环或程序seg出错。
它将进入无限循环或seg错误,具体取决于我声明数组的大小。例如,如果我将数组声明为大小为5,则会进入无限循环。但是,如果我将数组声明为大小为2,则会出现故障。
我正在通过运行来编译我的程序:
gcc -o myprog myprog.c
我正在通过运行来管道文件:
cat jobs.txt | ./myprog
值得注意的是,如果没有int x数组声明,程序运行正常。
我完全不知道可能是什么问题,任何想法?
答案 0 :(得分:2)
由于指针@import url("./fonts.css");
未初始化,因此您的行为未定义。 main.css
必须指向能够存储所需内容的内存区域(例如,请参阅user
)。
答案 1 :(得分:1)
正如您从其他答案中找到的那样,您的初始问题是char *user;
声明字符指针 未初始化(例如,它没有指向到任何有效的内存块)。虽然您可以使用malloc
,calloc
或realloc
进行动态分配,但这可能会导致您的情况过于复杂。
您真正需要的是声明一个足以容纳用户名的字符数组。 16
字符在这里绰绰有余。
下一个while (!feof(fp))
几乎总是错的。 (参见我的评论中的链接)。 scanf
可以返回发生的有效转化次数。在您的情况下,使用"%s..%c..%d..%d"
(4个转换说明符),返回4
将表示没有发生匹配或输入失败。因此,不要使用feof
检查,只需使用scanf
返回,例如
scanf("%*[^\n]"); //skipping header in the file.
while (scanf ("%15s %15s %d %d", user, process, &arrival, &duration) == 4)
printf ("%s\t%c\t%d\t%d\n", user, *process, arrival, duration);
(注意:表示简化的scanf
格式字符串"%15s %15s %d %d"
,arrival
被声明为字符数组(见下文)并读作 string (利用领先的空白空间跳过)然后使用*arrival
来挑选字符。这样就可以在输入<<1}时提供更健壮的方式来读取输入em>空格分隔而不是* tab分隔)
为避免在代码中使用幻数(例如16
),如果您需要一个常数,则声明一个常量,例如:
#define MAXC 16
int main (void) {
char user[MAXC] = "", process[MAXC] = "";
注意:可能看起来"%15s %15s %d %d"
违反了此规则,但遗憾的是,无法在scanf
字段宽度中包含常量变量说明符可防止读取超过15
个字符的数组 - 请记住,您必须为最终字符留出空间 - nul-terminatedating 字符。
完全放弃,您可以执行以下操作:
#include <stdio.h>
#define MAXC 16
int main (void) {
char user[MAXC] = "", process[MAXC] = "";
int arrival, duration;
scanf("%*[^\n]"); //skipping header in the file.
while (scanf ("%15s %15s %d %d", user, process, &arrival, &duration) == 4)
printf ("%s\t%c\t%d\t%d\n", user, *process, arrival, duration);
return 0;
}
示例使用/输出
$ ./bin/scanf_usr_arriv <dat/userprocarriv.txt
Jim A 2 5
Mary B 2 3
Sue D 5 5
Mary C 6 2
您可能还想考虑阅读所有&#34;输入行&#34;使用面向行的输入函数,如fgets
,然后在生成的缓冲区上调用sscanf
来解析每个变量。这样做的好处是允许对读取的行进行单独验证,然后对来自该行的每个变量的解析进行独立验证。
仔细看看,如果您有任何问题,请告诉我。