我有一个像这样的文件
GET /index.html k
GET /docencia.html k
GET /ejemplo.html k
我希望逐行阅读并使用此分隔符" "
将其拆分但是却给了我这个错误:segmentation fault(core dumped)
我不知道该尝试什么。
这是我的代码:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
char ordenes[150];
char *orden[3];
char *token;
int tok;
FILE *fp;
fp = fopen(argv[1], "r");
if (fp == NULL) {
printf("File error");
exit(1);
}
while (feof(fp) == 0) {
fgets(ordenes, sizeof(ordenes), fp);
printf("%s \n", ordenes);
token = strtok(ordenes, " ");
tok = 0;
while (token != NULL) {
orden[tok] = strdup(token);
tok++;
token = strtok(NULL, " ");
}
printf("\n%s\n", orden[0]);
printf("\n%s\n", orden[1]);
printf("\n%s\n", orden[2]);
}
fclose(fp);
}
当我拨打第一个strdup
时会显示错误。如果我在调用第一个strtok
后尝试打印令牌,它也会失败(相同的segmentation fault core dumped
),所以我想问题出在strtok
上。
答案 0 :(得分:5)
您不包含<string.h>
,因此编译器会在strtok的签名上应用默认参数提升,特别是它认为strtok返回int
。
因此,编译器将在作业中将int
到pointer to char
的强制操作符应用于
token = strtok(ordenes, " ");
并且此作业将编译为
token = (int->char*) strtok(ordenes, " ");
答案 1 :(得分:3)
您的代码中存在多个问题:
由于alinsoar被诊断为敏锐的眼睛,因此不包括<string.h>
。 strtok
未定义,编译器必须假定它返回int
,而不是int
,并且此char *
会以静默方式转换为gcc -Wall -W
。生成的代码调用未定义的行为,很可能会在64位目标上崩溃。您应该编译并启用所有警告,让编译器帮助避免这种愚蠢的错误。 clang -Weverything
或fp = fopen(argv[1], "r");
...
在调用argv[1]
之前,不检查命令行参数是否已传递给您的程序。如果没有传递参数,while (feof(fp) == 0)
是空指针。
while (fgets(ordenes, sizeof(ordenes), fp)) {...
不正确,请阅读Why is “while ( !feof (file) )” always wrong?。你应该写tok < 3
在将token
存储到orden
数组之前,您不会检查是否orden
。如果该行超过3个字段,则会导致缓冲区溢出。
在fgets()
打印所有3个条目之前,您不会检查是否确实找到了3个令牌。这也可能会调用未定义的行为,尤其是#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
char ordenes[150];
char *orden[3];
char *token;
int i, tok;
if (argc < 2) {
fprintf(stderr, "Missing command line argument\n");
exit(1);
}
FILE *fp = fopen(argv[1], "r");
if (fp == NULL) {
fprintf(stderr, "Cannot open input file %s: %s\n",
argv[1], strerror(errno));
exit(1);
}
while (fgets(ordenes, sizeof(ordenes), fp)) {
printf("%s", ordenes);
token = strtok(ordenes, " ");
for (tok = 0; tok < 3 && token != NULL; tok++) {
orden[tok] = strdup(token);
token = strtok(NULL, " ");
}
for (i = 0; i < tok; i++) {
printf("%s\n", orden[i]);
free(orden[i]);
}
printf("\n");
}
fclose(fp);
return 0;
}
无法读取您未检查的行时。
以下是改进版本:
str
答案 2 :(得分:0)
您可以执行以下操作:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void play_with_token(char *token, char const *delim)
{
if (token == NULL)
return;
printf(" %s", token);
play_with_token(strtok(NULL, delim), delim);
}
int main(int argc, char *argv[])
{
if (argc != 2)
return 1;
FILE *fp = fopen(argv[1], "r");
if (fp == NULL)
return 1;
char *line = NULL;
size_t len = 0;
ssize_t read;
while ((read = getline(&line, &len, fp)) != -1) {
printf("parsing line :");
char const *delim = " ";
play_with_token(strtok(line, delim), delim);
printf("\n");
}
free(line);
fclose(fp);
}
答案 3 :(得分:0)
对于初学者,您应该按照以下方式更改外部循环语句中的条件
while ( fgets(ordenes, sizeof(ordenes), fp) != NULL )
内循环中的条件至少应该写为
while ( tok < 3 && token != NULL) {
令牌应该循环输出,并且必须释放分配的内存。例如
for ( int i = 0; i < tok; i++ )
{
printf("\n%s\n", orden[i]);
free( orden[i]);
}
答案 4 :(得分:-1)
试试这个:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]){
char ordenes[150];
char *orden[3];
char *token;
int tok;
FILE *fp;
fp = fopen (argv[1], "r");
if(fp==NULL){
printf("File error");
exit(1);
}
while(fgets(ordenes, sizeof(ordenes), fp)){
printf("%s\n",ordenes);
token = strtok(ordenes, " ");
tok = 0;
while (token != NULL){
orden[tok++] = strdup(token);
token = strtok(NULL," ");
}
printf("\n%s\n",orden[0]);
printf("\n%s\n",orden[1]);
printf("\n%s\n",orden[2]);
free(orden[0]);free(orden[1]);free(orden[2]);
}
fclose(fp);
}