sscanf в C. Разделение неизвестного количества двойников в строке на массив

У меня есть похожие вопросы, но ни один из них не помог мне с моей проблемой. Я получаю строку с неизвестным количеством чисел с плавающей запятой, и мне нужно вырезать их отдельно в массив.

Что у меня есть:

   h=0;
   while(fstring[h]!='\n'){  //So first I count how many spaces there are in the string
            if(fstring[h]==' '){
                sc++;
            }
            h++;
    }
    vars=sc;
    for(h=0;h<vars;h++){
        sscanf(fstring,"%lf",&scanned);
        matrix[h]=scanned;
    }

Так почему это не работает? Каждый раз выдает ошибку..


person Randalfien    schedule 07.11.2010    source источник
comment
Подождите, это внезапно начало работать.. Прошу прощения за странный вопрос, но иногда компьютеры ведут себя странно..   -  person Randalfien    schedule 07.11.2010
comment
Что такое ASCII10? Разве это не должно быть 0?   -  person Eiko    schedule 07.11.2010
comment
Код, который вы разместили, будет постоянно сканировать первый номер.   -  person Martin Broadhurst    schedule 07.11.2010
comment
10 лучше было бы написать '\n'...   -  person zwol    schedule 07.11.2010
comment
Мартин Бродхерст: точно :) ...и как мне это изменить? Я имею в виду, что все еще использую sscanf?   -  person Randalfien    schedule 07.11.2010


Ответы (2)


Вместо этого вы можете сделать что-то вроде этого:

#include <stdio.h>

int main ()
{
    double fmatrix[100] = { 0 };
    double *matrix = fmatrix;
    double scanned;
    int bytesread;
    char string[100];
    char *fstring = string;
    int i;

    fgets ( string, 99, stdin );
    fstring = string;

    while ( sscanf ( fstring, "%lf%n", &scanned, &bytesread ) > 0 )
    {
        fstring += bytesread;
        *matrix++ = scanned;
    }

    matrix = fmatrix;

    for ( i = 0; i < 50; i++ )
    {
        printf ( "%lf\n", *matrix++ );
    }
}
person onemasse    schedule 07.11.2010
comment
Почему вам нужно иметь и char string[100];, и char *fstring = string;? - person Arc676; 11.06.2016
comment
Вы не можете делать приращения указателя на string, так как это не указатель. Вы можете изменить содержимое string, но не там, где оно размещено. - person onemasse; 20.06.2016
comment
Я попробовал это, используя только ‹code›fstring‹/code›, но это не сработало. Не могли бы вы точно объяснить, что произойдет, если вы просто используете указатель для ввода? Спасибо. - person Arc676; 20.06.2016
comment
Вам нужно выделить память для чтения, вы можете сделать это в стеке, используя char string[100];, или в куче, используя malloc(). Если вы этого не сделаете и/или не инициализируете fstring, код, если вам повезет, вылетит. - person onemasse; 20.06.2016
comment
Даже если вы можете уйти, используя только fstring, рекомендуется сохранять адрес того, что вы выделили в куче, и не манипулировать этим указателем, иначе вы не знаете, что делать free(). - person onemasse; 20.06.2016
comment
См. мой ответ, в котором используется этот код здесь. Когда я попытался использовать malloc для создания указателя и пропустить часть массива char, были проанализированы только первые 3 числа. - person Arc676; 20.06.2016
comment
Ну, в принципе, вы должны быть в состоянии заменить char string[100]; на char *string = malloc(100 * sizeof(char));. Обязательно проверьте string, чтобы не было NULL, хотя с современными операционными системами такое случается редко. Также не забудьте free(string); перед выходом. sizeof(char) может быть избыточным, но он не добавляет никакого наложения, и это хорошая практика. Если это то, что вы сделали, я не знаю, почему это не работает. - person onemasse; 20.06.2016
comment
Разве вы не говорили, что вам нужно сохранить исходный адрес указателя? Если у меня есть только один указатель, будет ли перемещение указателя (например, изменение места, на которое он указывает) вызывать утечку памяти при его освобождении? - person Arc676; 20.06.2016
comment
Давайте продолжим обсуждение в чате. - person onemasse; 20.06.2016

Я настоятельно рекомендую использовать здесь strtod, а не sscanf. Что-то вроде этого должно работать:

char *ptr, *endptr = fstring;
int h = 0;
do {
    ptr = endptr;
    matrix[h++] = strtod(ptr, &endptr);
} while (endptr != ptr && isspace(*endptr) && *endptr != '\n');

Выделение памяти и восстановление из неправильно сформированного ввода, оставленного в качестве упражнения.

person zwol    schedule 07.11.2010
comment
Это работает отлично. Спасибо! Единственная проблема в том, что я не понимаю этот код :) Не могли бы вы объяснить, как он работает, на действительно фундаментальном уровне? - person Randalfien; 07.11.2010
comment
У меня есть одна из этих проблем с этим кодом: ошибка сегментации/ошибка шины/превышен лимит памяти/превышен лимит стека. Есть ли проблема с распределением памяти? Мне нужно максимум 20 цифр, поэтому строка должна быть меньше, чем 20 умножить на 8 (количество цифр) плюс 19 пробелов, могу ли я ограничить это? - person Randalfien; 07.11.2010
comment
Вот объяснение strtod: linux.die.net/man/3/strtod Если это не та часть, которая не имеет смысла, пожалуйста, уточните, что вы не понимаете. Между тем, я не понимаю, как можно быть неуверенным в том, какую ошибку вы получаете — вы перечислили четыре совершенно разные вещи — но да, вы, вероятно, работает с конца вашего массива. Чтобы помочь с этим, я рекомендую вам опубликовать новый вопрос с полным тестовым примером, который люди могут скомпилировать и посмотреть на сбой. - person zwol; 09.11.2010
comment
Убедитесь, что ваша строка завершается нулем. Обычные строки должны быть такими, но если вы получили это в сообщении, как я, возможно, вы имеете дело с массивом символов, а strtod весело пробирается через вашу оперативную память, делая все возможное. - person Ant; 08.01.2015