Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/64.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 使用strtok时出现Seg故障_C_Segmentation Fault_Strtok - Fatal编程技术网

C 使用strtok时出现Seg故障

C 使用strtok时出现Seg故障,c,segmentation-fault,strtok,C,Segmentation Fault,Strtok,我试图从如下输入中读取每个数字: 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 =

我试图从如下输入中读取每个数字:

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;
}
#包括“header.h”
#包括
内部主(空){
int8_t*line=malloc(sizeof(int8_t)*75);
内部温度;
int32_t最小值,最大值;
int32_t电流;
stdin=fopen(“stdin”、“r”);
而(fgets(线条,75*sizeof(int8_t),标准尺寸)){
printf(“%s”,第行);
temp=strtok(第“\n\t”行);
最大值=最小值=原子(温度);
while(temp!=NULL){
电流=atoi(温度);
temp=strtok(空,“\n\t”);
如果(电流<最小值)
最小值=电流;
如果(当前>最大值)
最大值=电流;
} 
printf(“\n最小值和最大值:%d%d\n”,最小值和最大值);
}
printf(“\n”);
返回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
#ifndef头
#定义标题
#包括
#包括
#包括
typedef char int8_t;
typedef签名短整型16_t;
typedef签名int int32_t;
typedef签名长整型64_t;
typedef无符号字符uint8;
typedef无符号短整数uint16\u t;
typedef unsigned int uint32\u t;
typedef无符号长整数uint64\u t;
#恩迪夫
我只是不明白这可能是错的。谢谢

stdin = fopen("stdin", "r");
这不是你想象的那样。这将尝试打开当前目录中名为“stdin”的文件。它不打开标准输入流

您很可能没有此名称的文件,因此此函数可能会失败并返回NULL。因为不检查返回值,所以将空指针传递给
fgets
。这将调用未定义的行为,在本例中表现为崩溃

程序启动时,标准输入流已打开。因此,删除
fopen
调用,它应该会工作。

好的,所以

  • 您的
    在我的编译器上中断,因为它重新定义了标准保留的标识符
    int8\t
    等。(编译器抱怨的不太正确,因为没有包含相关的头,但您有。)如果您定义自己的类型,请使用自己的标识符。或者将
    包含在“真实”intX\t类型中(是的,我知道某个“大”编译器没有该头)

  • 当然,最简单的方法是对字符串使用
    char*
    ,而不是
    int8\t*
    。(有符号的
    char
    是由实现定义的,无论如何,一个好的编译器会大声抱怨没有使用
    char*
    的许多隐式强制转换。)

  • 对于
    minim
    maxim
    ,您使用了确切的宽度类型
    int32\t
    ,但忽略了使用适当的
    printf()
    宽度说明符来配合(
    PRId32
    ,在
    中指定)。由于我看不到对精确宽度类型的任何具体需求,我将它们替换为普通的
    int
    (仅
    %d
    就足够了)

  • 完成此操作后,请删除
    sizeof(char)
    ,因为这是定义
    1

  • 执行检查返回函数值
    fopen()
    可能会失败。确保没有

  • 不要“重用”stdin文件描述符。这让人很困惑。您的
    stdin
    是来自终端还是来自文件或管道取决于您如何调用可执行文件。如果打开文件,请使用
    文件*句柄\u名称
    ,而不是
    stdin
    。此外,
    stdin
    是一个打开的文件描述符(即程序的标准输入),因此您必须使用
    freopen()
    ,而不是
    fopen()
    ,才能正确地从其他源接收它。最简单的事情是按原样实际使用
    stdin
    (这也为您使用程序提供了最大的灵活性)

  • 释放您获得的资源<代码>释放()内存<代码>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;
    }
    

    #include//您不需要打开
    stdin
    ,它已经打开了。是否有任何理由不在此处使用
    scanf
    ?给定简单而规则的输入。
    stdin=fopen(“stdin”,“r”)--正在打开一个名为“stdin”的文件进行读取。在从
    stdin
    句柄读取之前,也不会检查打开该文件是否成功。未定义的行为,你会死。@WeatherVane:经常建议使用
    fgets()
    一次读取一行并在内存中解析它(而不是
    *scanf()
    )。这里没有批评的理由(如果他做得对就好了)。在检查
    temp
    上的
    atoi
    之前,先检查它是否为
    NULL
    。未定义的行为会导致死亡。
    uint8\u t
    等是标准库(
    )保留的标识符,使用一致性编译器编译头.h会因此失败。@Marcus:您没有检查。@DevSolar这不是错误。它正确地读取了第一行,然后它就断了,我忘了在帖子中写这个……还要注意,你不一定能像那样重新分配
    stdin
    。在现代Linux上,您可能可以。在经典的Unix上,它可能不起作用。这就是为什么该函数是标准C的一部分(尽管我链接到POSIX规范)。不,字符没有定义为8位,而是定义为具有
    char\u位
    位。我保留OP的源代码格式是为了让更改对他来说更加突出(源代码格式是o的问题)
    ./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