我正在尝试从输入中读取每个数字,如下所示:
179 2358 5197 867
5541 172 4294 1397
2637 136 3222 591
...并逐行获取每行的最小值/最大值,然后使用strtok获取行中的每个数字,但在第二个while循环中出现seg错误。
代码:
#include "header.h"
#include <string.h>
int main(void) {
int8_t* line = malloc(sizeof(int8_t) * 75);
int8_t* temp;
int32_t minim, maxim;
int32_t current;
stdin = fopen("stdin", "r");
while (fgets(line, 75 * sizeof(int8_t), stdin)) {
printf("%s", line);
temp = strtok(line," \n\t");
maxim = minim = atoi(temp);
while (temp != NULL) {
current = atoi(temp);
temp = strtok(NULL, " \n\t");
if (current < minim)
minim = current;
if (current > maxim)
maxim = current;
}
printf("\nMin and max: %d %d\n", minim, maxim);
}
printf("\n");
return 0;
}
标题:
#ifndef HEADER_H
# define HEADER_H
# include <stdio.h>
# include <stdlib.h>
# include <stdbool.h>
typedef char int8_t;
typedef signed short int int16_t;
typedef signed int int32_t;
typedef signed long long int int64_t;
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long long int uint64_t;
#endif
我只是不知道它可能是错的。感谢。
答案 0 :(得分:4)
好的,所以...
您的<header.h>
打破了我的编译器,因为它重新定义了标识符int8_t
等。按标准保留。 (投诉编译器不太正确,因为没有包含相关的标题,但是你有。)如果您定义自己的类型,请使用您自己的标识符。或者将<stdint.h>
包含在“真正的”intX_t类型中(是的,我知道某个“大”编译器没有该标题)。
当然,最简单的方法是将char *
用于字符串而不是int8_t *
。 (char
的签名是实现定义的,无论如何,一个好的编译器会相当大声地抱怨使用char *
涉及的许多隐式转换而不是。)
您对int32_t
和minim
使用精确宽度类型maxim
,但忽略使用正确的printf()
宽度说明符( PRId32
中指定的<inttypes.h>
。由于我看不出对精确宽度类型的任何特定需求,我将其替换为普通int
(仅%d
就足够了)。
完成后,请删除sizeof( char )
的提及,因为按照定义 1
。
检查返回函数值。 fopen()
可能会失败。确保没有。
不要“重用”stdin
文件描述符。这只会令人困惑。您的stdin
来自终端,文件还是管道,取决于您如何调用可执行文件。如果您打开文件,请使用FILE * handle_name
,而不是stdin
。此外,stdin
是一个打开的文件描述符(即您的程序的标准输入),因此您必须使用freopen()
,而不是fopen()
才能拥有它从不同的来源正确接收。最简单的方法是实际使用stdin
(这也为使用您的程序提供了最大的灵活性)。
执行释放您获得的资源。 free()
记忆。 fclose()
个文件。许多操作系统可以保护您免受此类疏忽,并在您之后进行清理。有些人没有。
一旦你解决了那些你在评论中打喷嚏的问题......
#include <stdlib.h> // <-- added
#include <stdio.h> // <-- added
#include <string.h>
int main() {
char* line = malloc(75); // <-- turned to char *
char* temp; // <-- turned to char *
int minim, maxim; // <-- turned to int
int current; // <-- turned to int
while (fgets(line, 75, stdin)) { // <-- using stdin directly
printf("%s", line);
temp = strtok(line," \n\t");
maxim = minim = atoi(temp);
while (temp != NULL) {
current = atoi(temp);
temp = strtok(NULL, " \n\t");
if (current < minim)
minim = current;
if (current > maxim)
maxim = current;
}
printf("\nMin and max: %d %d\n", minim, maxim);
}
printf("\n");
free( line ); // <-- releasing memory
return 0;
}
...你的程序有效:
./testme.exe < file.dat # feeding file.dat to stdin
179 2358 5197 867
Min and max: 179 5197
5541 172 4294 1397
Min and max: 172 5541
2637 136 3222 591
Min and max: 136 3222
这里的课程:干净利落的代码。启用最严格的编译器警告,并注意它们。
至于覆盖stdin
与fopen()
的结果一样,标准状态(强调我的):
229)[...] [
stderr
,stdin
或stdout
] 无需修改左值 {可以分配{1}}功能。
答案 1 :(得分:0)
stdin = fopen("stdin", "r");
这不符合您的想法。这会尝试在名为“stdin”的当前目录中打开一个文件。它不打开标准输入流。
您很可能没有此名称的文件,因此此函数可能会失败并返回NULL。并且因为您没有检查返回值,所以将NULL指针传递给fgets
。这会调用未定义的行为,在这种情况下表现为崩溃。
程序启动时,标准输入流已经打开。因此,请删除fopen
电话,它应该有效。