简体   繁体   English

通过strtok将ac字符串分解为令牌

[英]Breaking a c string into tokens through strtok

In the following piece of code, i see that after breaking userHostPairs in tokens and assigning to itself doesn't work. 在下面的代码中,我看到在令牌中破坏userHostPairs并将其分配给自己后不起作用。 After breaking into tokens i print userHostPairs in loop and in the same loop i also print 0th element always through printf("0Printing after strtok = %s",userHostPairs[0]); 分成令牌后,我循环打印userHostPairs ,并且在同一循环中,我也始终通过printf("0Printing after strtok = %s",userHostPairs[0]);始终打印第0个元素printf("0Printing after strtok = %s",userHostPairs[0]); which prints weird values(most probably the last fetched value). 打印奇怪的值(很可能是最后获取的值)。

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.
        }
}

Output: 输出:

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). 打印奇怪的值(很可能是最后获取的值)。

this is because of several errors in your code 这是因为您的代码中有几个错误

            char temp[100];

            userHostPairs[i] = strtok(temp,"@");
            userHostPairs[i] = strtok(NULL,"@");

the assignments are not what you want for 3 reasons : 作业不是您想要的,原因有3个:

  • you replace the mallocd block (rather than probably to strcpy in it), so you create a memory leak 您替换了mallocd块(而不是可能在其中进行strcpy ),因此创建了内存泄漏
  • you assign two times the same entry in userHostPairs , so the first result of strtok is lost 您在userHostPairs中分配了两次相同的条目,因此strtok的第一个结果丢失了
  • strtok returns pointers in temp and you modify temps the next loop so the previous results are broken strtok的返回温度指针,你修改临时工的下一个循环,使之前的结果被打破

Of course when you will go out of the scope of temp any uses to pointer saved in userHostPairs will have an undefined behavior, but this is not the reason of the result you see because your writes are in the scope of temp 当然,当您超出temp的范围时,任何用于userHostPairs中保存的指针的用法都会具有未定义的行为,但这不是您看到的结果的原因,因为您的写入在temp的范围内


Example : 范例:

#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;
}

Note if you have strdup you can replace 请注意,如果您有strdup ,则可以替换

    a1[rank] = malloc(strlen(p1) + 1);
    strcpy(a1[rank], p1);

    a2[rank] = malloc(strlen(p2) + 1);
    strcpy(a2[rank], p2);

by 通过

    a1[rank] = strsup(p1);
    a2[rank] = strdup(p2);

Having the file f containing : 文件f包含:

aze@qsd@
wxc@iop
iop@jkl

Compilation and execution : 编译执行:

pi@raspberrypi:/tmp $ ./a.out
'aze' / 'qsd'
'wxc' / 'iop'
'iop' / 'jkl'
pi@raspberrypi:/tmp $ 

Execution under valgrind : 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

If you do not want to limit the number of elements in the arrays you can use malloc then realloc for the arrays : 如果您不想限制数组中元素的数量,则可以使用malloc然后为数组重新分配

#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;
}

With the same file f , compilation and execution : 使用相同的文件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 $ 

Execution under valgrind : 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 $ 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM