通过 strtok 将 c 字符串分解为标记
Breaking a c string into tokens through strtok
在下面的代码中,我看到在标记中打破 userHostPairs
并分配给自身后不起作用。
进入标记后,我在循环中打印 userHostPairs
,在同一个循环中,我也总是通过 printf("0Printing after strtok = %s",userHostPairs[0]);
打印第 0 个元素,它打印奇怪的值(很可能是最后获取的值)。
FILE* fp;
char line[100];
char* userHostPairs[100];
fp = fopen("somefile", "r");
//READING THE FILE LINE BY LINE. WORKS FINE
int count =0;
while (fgets(line, sizeof(line), fp) != NULL ) {
userHostPairs[count]=malloc(MAX_LINE_SIZE);
strcpy(userHostPairs[count],line);
count++;
}
///PROBLEMATIC CODE////////////////////
for(i=0;i<count;i++)
{
char temp[100];
strcpy(temp,userHostPairs[i]);
userHostPairs[i] = strtok(temp,"@");
userHostPairs[i] = strtok(NULL,"@");
printf("Printing after strtok = %s",userHostPairs[i]);
printf("0Printing after strtok = %s",userHostPairs[0]); //This 0th element is always some random(or last) value fetched.
}
}
输出:
Printing in strtok = 10.238.178.136
0Printing in strtok = 10.238.178.136
Printing in strtok = 10.238.152.101
0Printing in strtok = 10.238.152.101
Printing in strtok = eaasrt
0Printing in strtok = eaasrt
Printing in strtok = eaasrt7
0Printing in strtok = aasrt7
prints weird values(most probably the last fetched value).
这是因为您的代码中有几个错误
char temp[100];
userHostPairs[i] = strtok(temp,"@");
userHostPairs[i] = strtok(NULL,"@");
作业不是您想要的,原因有 3 个:
- 你替换了 mallocd 块(而不是可能 strcpy ),所以你造成了内存泄漏
- 您在 userHostPairs 中分配了两次相同的条目,因此 strtok 的第一个结果丢失了
- strtok returns指针在temp然后你修改下temps循环所以之前的结果被打破
当然,当您超出 temp 的范围时,对保存在 userHostPairs 中的指针的任何使用都会有未定义的行为,但这不是您看到结果的原因,因为您的写入在 temp
的范围内
示例:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
size_t read(size_t sz, char *a1[sz], char * a2[sz])
{
FILE* fp = fopen("f", "r");
if (fp == 0)
return 0;
char line[50];
size_t rank;
for (rank = 0; rank != sz; ++rank) {
if (fgets(line, sizeof(line), fp) == NULL)
break;
char * p1, * p2;
if (((p1 = strtok(line, "@")) == NULL) ||
((p2 = strtok(NULL, "@\n")) == NULL))
break;
a1[rank] = malloc(strlen(p1) + 1);
strcpy(a1[rank], p1);
a2[rank] = malloc(strlen(p2) + 1);
strcpy(a2[rank], p2);
}
fclose(fp);
return rank;
}
#define N 50
int main()
{
char * a1[N];
char * a2[N];
size_t n = read(N, a1, a2);
for (size_t i = 0; i != n; ++i)
printf("'%s' / '%s'\n", a1[i], a2[i]);
/* ... */
/* free resources */
for (size_t i = 0; i != n; ++i) {
free(a1[i]);
free(a2[i]);
}
return 0;
}
注意如果你有strdup你可以替换
a1[rank] = malloc(strlen(p1) + 1);
strcpy(a1[rank], p1);
a2[rank] = malloc(strlen(p2) + 1);
strcpy(a2[rank], p2);
来自
a1[rank] = strsup(p1);
a2[rank] = strdup(p2);
文件 f 包含:
aze@qsd@
wxc@iop
iop@jkl
编译与执行:
pi@raspberrypi:/tmp $ ./a.out
'aze' / 'qsd'
'wxc' / 'iop'
'iop' / 'jkl'
pi@raspberrypi:/tmp $
在valgrind下执行:
pi@raspberrypi:/tmp $ valgrind ./a.out
==6244== Memcheck, a memory error detector
==6244== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==6244== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==6244== Command: ./a.out
==6244==
'aze' / 'qsd'
'wxc' / 'iop'
'iop' / 'jkl'
==6244==
==6244== HEAP SUMMARY:
==6244== in use at exit: 0 bytes in 0 blocks
==6244== total heap usage: 9 allocs, 9 frees, 5,496 bytes allocated
==6244==
==6244== All heap blocks were freed -- no leaks are possible
==6244==
==6244== For counts of detected and suppressed errors, rerun with: -v
==6244== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 3)
pi@raspberrypi:/tmp $ cat f
如果您不想限制数组中元素的数量,您可以使用 malloc 然后对数组使用 realloc :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
size_t read(char *** a1, char *** a2)
{
*a1 = malloc(0);
*a2 = malloc(0);
FILE* fp = fopen("f", "r");
if (fp == 0)
return 0;
char line[50];
size_t rank = 0;
while (fgets(line, sizeof(line), fp) != NULL) {
char * p1, * p2;
if (((p1 = strtok(line, "@")) == NULL) ||
((p2 = strtok(NULL, "@\n")) == NULL))
break;
*a1 = realloc(*a1, (rank+1) * sizeof(char *));
(*a1)[rank] = malloc(strlen(p1) + 1);
strcpy((*a1)[rank], p1);
*a2 = realloc(*a2, (rank+1) * sizeof(char *));
(*a2)[rank] = malloc(strlen(p2) + 1);
strcpy((*a2)[rank], p2);
rank += 1;
}
fclose(fp);
return rank;
}
int main()
{
char ** a1;
char ** a2;
size_t n = read(&a1, &a2);
for (size_t i = 0; i != n; ++i)
printf("'%s' / '%s'\n", a1[i], a2[i]);
/* ... */
/* free resources */
for (size_t i = 0; i != n; ++i) {
free(a1[i]);
free(a2[i]);
}
free(a1);
free(a2);
return 0;
}
同一个文件f,编译执行:
pi@raspberrypi:/tmp $ gcc -g -pedantic -Wextra -Wall st.c
pi@raspberrypi:/tmp $ ./a.out
'aze' / 'qsd'
'wxc' / 'iop'
'iop' / 'jkl'
pi@raspberrypi:/tmp $
在valgrind下执行:
pi@raspberrypi:/tmp $ valgrind ./a.out
==6423== Memcheck, a memory error detector
==6423== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==6423== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==6423== Command: ./a.out
==6423==
'aze' / 'qsd'
'wxc' / 'iop'
'iop' / 'jkl'
==6423==
==6423== HEAP SUMMARY:
==6423== in use at exit: 0 bytes in 0 blocks
==6423== total heap usage: 17 allocs, 17 frees, 5,544 bytes allocated
==6423==
==6423== All heap blocks were freed -- no leaks are possible
==6423==
==6423== For counts of detected and suppressed errors, rerun with: -v
==6423== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 3)
pi@raspberrypi:/tmp $
在下面的代码中,我看到在标记中打破 userHostPairs
并分配给自身后不起作用。
进入标记后,我在循环中打印 userHostPairs
,在同一个循环中,我也总是通过 printf("0Printing after strtok = %s",userHostPairs[0]);
打印第 0 个元素,它打印奇怪的值(很可能是最后获取的值)。
FILE* fp;
char line[100];
char* userHostPairs[100];
fp = fopen("somefile", "r");
//READING THE FILE LINE BY LINE. WORKS FINE
int count =0;
while (fgets(line, sizeof(line), fp) != NULL ) {
userHostPairs[count]=malloc(MAX_LINE_SIZE);
strcpy(userHostPairs[count],line);
count++;
}
///PROBLEMATIC CODE////////////////////
for(i=0;i<count;i++)
{
char temp[100];
strcpy(temp,userHostPairs[i]);
userHostPairs[i] = strtok(temp,"@");
userHostPairs[i] = strtok(NULL,"@");
printf("Printing after strtok = %s",userHostPairs[i]);
printf("0Printing after strtok = %s",userHostPairs[0]); //This 0th element is always some random(or last) value fetched.
}
}
输出:
Printing in strtok = 10.238.178.136
0Printing in strtok = 10.238.178.136
Printing in strtok = 10.238.152.101
0Printing in strtok = 10.238.152.101
Printing in strtok = eaasrt
0Printing in strtok = eaasrt
Printing in strtok = eaasrt7
0Printing in strtok = aasrt7
prints weird values(most probably the last fetched value).
这是因为您的代码中有几个错误
char temp[100];
userHostPairs[i] = strtok(temp,"@");
userHostPairs[i] = strtok(NULL,"@");
作业不是您想要的,原因有 3 个:
- 你替换了 mallocd 块(而不是可能 strcpy ),所以你造成了内存泄漏
- 您在 userHostPairs 中分配了两次相同的条目,因此 strtok 的第一个结果丢失了
- strtok returns指针在temp然后你修改下temps循环所以之前的结果被打破
当然,当您超出 temp 的范围时,对保存在 userHostPairs 中的指针的任何使用都会有未定义的行为,但这不是您看到结果的原因,因为您的写入在 temp
的范围内示例:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
size_t read(size_t sz, char *a1[sz], char * a2[sz])
{
FILE* fp = fopen("f", "r");
if (fp == 0)
return 0;
char line[50];
size_t rank;
for (rank = 0; rank != sz; ++rank) {
if (fgets(line, sizeof(line), fp) == NULL)
break;
char * p1, * p2;
if (((p1 = strtok(line, "@")) == NULL) ||
((p2 = strtok(NULL, "@\n")) == NULL))
break;
a1[rank] = malloc(strlen(p1) + 1);
strcpy(a1[rank], p1);
a2[rank] = malloc(strlen(p2) + 1);
strcpy(a2[rank], p2);
}
fclose(fp);
return rank;
}
#define N 50
int main()
{
char * a1[N];
char * a2[N];
size_t n = read(N, a1, a2);
for (size_t i = 0; i != n; ++i)
printf("'%s' / '%s'\n", a1[i], a2[i]);
/* ... */
/* free resources */
for (size_t i = 0; i != n; ++i) {
free(a1[i]);
free(a2[i]);
}
return 0;
}
注意如果你有strdup你可以替换
a1[rank] = malloc(strlen(p1) + 1);
strcpy(a1[rank], p1);
a2[rank] = malloc(strlen(p2) + 1);
strcpy(a2[rank], p2);
来自
a1[rank] = strsup(p1);
a2[rank] = strdup(p2);
文件 f 包含:
aze@qsd@
wxc@iop
iop@jkl
编译与执行:
pi@raspberrypi:/tmp $ ./a.out
'aze' / 'qsd'
'wxc' / 'iop'
'iop' / 'jkl'
pi@raspberrypi:/tmp $
在valgrind下执行:
pi@raspberrypi:/tmp $ valgrind ./a.out
==6244== Memcheck, a memory error detector
==6244== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==6244== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==6244== Command: ./a.out
==6244==
'aze' / 'qsd'
'wxc' / 'iop'
'iop' / 'jkl'
==6244==
==6244== HEAP SUMMARY:
==6244== in use at exit: 0 bytes in 0 blocks
==6244== total heap usage: 9 allocs, 9 frees, 5,496 bytes allocated
==6244==
==6244== All heap blocks were freed -- no leaks are possible
==6244==
==6244== For counts of detected and suppressed errors, rerun with: -v
==6244== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 3)
pi@raspberrypi:/tmp $ cat f
如果您不想限制数组中元素的数量,您可以使用 malloc 然后对数组使用 realloc :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
size_t read(char *** a1, char *** a2)
{
*a1 = malloc(0);
*a2 = malloc(0);
FILE* fp = fopen("f", "r");
if (fp == 0)
return 0;
char line[50];
size_t rank = 0;
while (fgets(line, sizeof(line), fp) != NULL) {
char * p1, * p2;
if (((p1 = strtok(line, "@")) == NULL) ||
((p2 = strtok(NULL, "@\n")) == NULL))
break;
*a1 = realloc(*a1, (rank+1) * sizeof(char *));
(*a1)[rank] = malloc(strlen(p1) + 1);
strcpy((*a1)[rank], p1);
*a2 = realloc(*a2, (rank+1) * sizeof(char *));
(*a2)[rank] = malloc(strlen(p2) + 1);
strcpy((*a2)[rank], p2);
rank += 1;
}
fclose(fp);
return rank;
}
int main()
{
char ** a1;
char ** a2;
size_t n = read(&a1, &a2);
for (size_t i = 0; i != n; ++i)
printf("'%s' / '%s'\n", a1[i], a2[i]);
/* ... */
/* free resources */
for (size_t i = 0; i != n; ++i) {
free(a1[i]);
free(a2[i]);
}
free(a1);
free(a2);
return 0;
}
同一个文件f,编译执行:
pi@raspberrypi:/tmp $ gcc -g -pedantic -Wextra -Wall st.c
pi@raspberrypi:/tmp $ ./a.out
'aze' / 'qsd'
'wxc' / 'iop'
'iop' / 'jkl'
pi@raspberrypi:/tmp $
在valgrind下执行:
pi@raspberrypi:/tmp $ valgrind ./a.out
==6423== Memcheck, a memory error detector
==6423== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==6423== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==6423== Command: ./a.out
==6423==
'aze' / 'qsd'
'wxc' / 'iop'
'iop' / 'jkl'
==6423==
==6423== HEAP SUMMARY:
==6423== in use at exit: 0 bytes in 0 blocks
==6423== total heap usage: 17 allocs, 17 frees, 5,544 bytes allocated
==6423==
==6423== All heap blocks were freed -- no leaks are possible
==6423==
==6423== For counts of detected and suppressed errors, rerun with: -v
==6423== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 3)
pi@raspberrypi:/tmp $