Перебор строк в файле и сравнение с предыдущей строкой - PullRequest
1 голос
/ 10 июля 2019

Я хотел бы проверить, эквивалентна ли первая запись предыдущей строки следующей строке.Вот некоторые данные, которые я использую:

Config,Prob,MAN,ATL,CVERT,TVERT,RIB,SCAP,PHUM,DHUM,PRAD,DRAD,CARP,PMC,DMC,PHX
LH,1,2,2,7,13,13,2,2,2,1,1,6,2,2,24
LH,1,0,0,0,0,9,1,2,2,2,2,12,2,2,18
LH,3,0,0,0,0,4,0,0,0,0,0,0,0,0,0
LH,1,0,0,0,13,24,2,2,2,2,2,12,2,2,24
LH,1,0,0,1,13,15,2,0,0,2,2,0,0,0,6
LH,1,0,0,0,0,10,0,1,1,0,0,0,0,0,18
LH,1,0,2,7,3,7,2,2,2,2,2,12,2,2,24
LH,1,0,0,2,0,14,1,2,2,2,2,0,0,0,18
LK,1,0,0,0,0,13,0,0,0,1,1,6,0,0,0
LK,1,2,2,7,13,17,1,0,0,0,0,0,0,0,6
LK,1,0,0,0,10,23,1,1,1,1,1,6,1,1,18
LK,1,2,2,7,0,18,2,0,0,1,1,12,2,2,24
LK,1,0,0,3,0,8,0,0,0,2,2,12,2,2,24
LK,1,2,2,7,0,8,0,0,0,2,2,12,2,2,24
LK,3,2,2,7,13,22,2,2,2,2,2,12,2,2,24
LK,1,2,2,7,0,2,0,0,0,0,0,0,0,0,0
LK,1,2,2,6,0,11,0,2,2,0,0,12,2,2,18

Так что в этом случае я хотел бы подсчитать все времена, когда первая запись строки изменяется.В этих данных это будет эквивалентно двум (От конфигурации до LH, затем от LH до LK).Вот мой попытанный код:

int agents = 0;
int nrows = 0;
char buf[1024];
char *temp;
const char *tok;

while (fgets(buf, 1024, ifp)){
    tok = strtok(buf,",");
    if(nrows>0){
        if(strcmp(temp,tok) != 0){
            ++agents;
        }
    }

    temp = tok;
    nrows++;
}

Моя логика заключалась в том, что мы хотим пропустить первую итерацию, поскольку temp ничего не содержит, но будет назначен после завершения цикла.При следующем запуске цикла мы получим следующую строку, присвоенную tok, по сравнению с temp, в которой есть предыдущая строка.Если они отличаются, увеличивайте, если нет, продолжайте.Назначьте temp на tok и повторите снова.Тем не менее, agents по-прежнему возвращает 0 после цикла.

Поэтому моя логика несовершенна, хотя я не уверен, что это за часть.Спасибо за любую помощь, спасибо.

Ответы [ 2 ]

1 голос
/ 10 июля 2019

Сохраните первый токен первой строки («Конфиг» в вашем примере) и сравните его со следующей строкой. Когда вы найдете изменение, замените сохраненный токен. Используйте счетчик для подсчета изменений (сколько раз вы заменили сохраненный токен).

Вы были близки, но то, как вы думаете, что копируете токен во временное пространство, неверно. Простым решением будет использование массива фиксированного размера для этого временного, а когда вы хотите скопировать, используйте strcpy().

Полный пример:

#include <stdio.h>
#include <string.h>

int main(void)
{
    FILE* fp;
    const int sz = 256;
    char buffer[sz], tmp[sz] = {0};

    fp = fopen("file.txt", "r");

    int changes = 0;
    while(fgets(buffer, sz, (FILE*) fp))
    {
        // Eat trailining newline of fgets()
        if(buffer[strlen(buffer) - 1] == '\n')
            buffer[strlen(buffer) - 1] = '\0';
        const char* token = strtok(buffer, ",");
        if(strcmp(tmp, token) != 0)
        {
            strcpy(tmp, token);
            changes++;
        }
    }
    // changes - 1, because we always count the first line as a change
    printf("Changes = %d\n", --changes);
    fclose(fp);
    return 0;
}

Выход:

Изменения = 2

0 голосов
/ 10 июля 2019

вы также можете использовать fscanf() семейство функций, код намного проще и короче! :

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int main(){
    FILE* file = fopen("data.txt", "r");
    char token[256];
    char tmp[256];
    int  read = -1;
    int  n    = 0;

    while (1){
        read = fscanf(file, "%[^,]", token);
        fscanf(file, "%*[^\n]\n");/*go to next line*/
        if(read != 1)
            break;
        if(strcmp(token, tmp) != 0){
            ++n;
            strcpy(tmp, token);
        }
    }
    fclose(file);
    printf("n = %d\n", --n);
    return 0;
}

вывод:

n = 2
Process finished with exit code 0
...