2010-11-05 5 views
0

Когда я использую sscanf() в следующем коде, он берет всю строку и по какой-то причине помещает ее в первую строку, и я не вижу никаких проблем с ней. Выход из Msg() выходит как PatchVersion=1.1.1.5 = °?¦§-sscanf() не распознает формат должным образом

файл выглядит следующим образом (за исключением каждый из них является новая линия, не знаю, почему он показывает, как один на StackOverflow)

PatchVersion=1.1.1.5 
ProductName=tf 
appID=440 

Код:

bool ParseSteamFile() 
{ 
    FileHandle_t file; 
    file = filesystem->Open("steam.inf", "r", "MOD"); 

    if(file) 
    { 
     int size = filesystem->Size(file); 
     char *line = new char[size + 1]; 

     while(!filesystem->EndOfFile(file)) 
     { 
      char *subLine = filesystem->ReadLine(line, size, file); 

      if(strstr(subLine, "PatchVersion")) 
      { 
       char *name = new char[32]; 
       char *value = new char[32]; 
       sscanf(subLine, "%s=%s", name, value); 

       Msg("%s = %s\n", name, value); 
      } 
      else if(strstr(subLine, "ProductName")) 
      { 
       char *name = new char[32]; 
       char *value = new char[32]; 
       sscanf(subLine, "%s=%s", name, value); 

       Msg("%s = %s\n", name, value); 
      } 
     } 

     return true; 
    } 
    else 
    { 
     Msg("Failed to find the Steam Information File (steam.inf)\n"); 
     filesystem->Close(file); 
     return false; 
    } 

    filesystem->Close(file); 
    return false; 
} 
+2

Для дальнейшего использования, * пожалуйста * опубликовать минимальный пример кода, то есть минимальный компилируемый код, который воспроизводит ошибку (вам мог бы сделать этот пример примерно в 4 строках). Это облегчает чтение другим пользователям, и вы, вероятно, найдете ошибку в этом процессе. –

ответ

0

из страницы руководства по зсапЕ, относительно% S:

Матчи последовательность без пробельных символов; следующий указатель должен быть указателем на массив символов, который достаточно длинный, чтобы удерживать входную последовательность и завершающий нулевой символ ('\ 0'), который добавляется автоматически. Входная строка останавливается в белом пространстве или при максимальной ширине поля, в зависимости от того, что произойдет раньше.

2

%s является «жадным», то есть он продолжает читать до тех пор, пока он не ударит по whitspace (или новой строке, или EOF). Символ '=' не является ни одним из них, поэтому sscanf просто продолжает, сопоставляя всю строку для первого %s.

Возможно, вам лучше использовать (например) strtok() или простой парсер по-характеру.

+0

Или можно попробовать использовать boost :: regex. – CashCow

+0

Или потокобезопасный strtok_r() – mmatloka

+0

Даже std :: string и find сделают трюк. – CashCow

0

% s будет читать символы до тех пор, пока не встретится пробел. Поскольку перед/после знака «=» нет пробелов, читается вся строка.

4

Одно решение было бы использовать (а недостаточно используются, на мой взгляд) характер группы спецификатора формата:

sscanf(subLine, "%[^=]=%s", name, value); 

Кроме того, вы должны использовать возвращаемое значение sscanf(), чтобы убедиться, что вы действительно получите оба значения , прежде чем полагаться на них.

0

Ваше использование массивов - очень плохой метод C++. Вы можете использовать потоки, но если вы настаиваете на использовании sscanf и массивов, то по крайней мере используйте вектор для управления своей памятью.

Вы можете распечатать именно то, что находится в subLine, и что делает Msg. Это ваш собственный код, потому что я никогда не слышал о FileHandle_t. Я знаю, что у него есть метод, который возвращает char *, который, по-видимому, вам нужно управлять.

Регулярные выражения являются частью библиотеки ускорения и вскоре будут в стандартной библиотеке. Они довольно «стандартные», и вы можете использовать его для анализа вашей линии.

(повышение :: регулярное выражение или tr1 :: регулярное выражение, если у вас есть, VS2008 имеет его)