Взлом строки c в токены через strtok - PullRequest
0 голосов
/ 04 июня 2019

В следующем фрагменте кода я вижу, что после взлома userHostPairs в токенах и присвоения себе не работает.После взлома токенов я печатаю userHostPairs в цикле и в том же цикле, я также печатаю 0-й элемент всегда через printf("0Printing after strtok = %s",userHostPairs[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

1 Ответ

3 голосов
/ 04 июня 2019

печатает странные значения (скорее всего, последнее извлеченное значение).

это из-за нескольких ошибок в вашем коде

            char temp[100];

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

назначения не теВы хотите по 3 причинам:

  • вы заменяете блок mallocd (а не strcpy в нем), поэтому вы создаете утечку памяти
  • вы дважды присваиваете одну и ту же запись в userHostPairs , поэтому первый результат strtok теряется
  • strtok возвращает указатели в temp и вы изменяете temp следующий цикл, чтобы предыдущие результаты были прерваны

Конечно, когда вы выйдете за рамки 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 yoВы можете заменить

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