2015-10-02 2 views
0

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

Я использую метод scanf() для изменения значения из строки, но scanf() не изменяет только значение из параметризованной строки, которое оно также меняет и значение из других строк.

Теперь мой вопрос: я просто избалованный от Java-разработчика, и я слишком глупый, чтобы использовать его правильно? Я не вижу, где я делаю ошибку.

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

int main(int argc, char *argv[]) 
{ 
    char lFileType[] = ".txt"; 
    char lFilePath[] = "C:\\Notenverwaltungssystem"; 
    char lFileFinalPath[] = ""; 
    char lFileName[] = ""; 

    printf("lFileType before scanf: "); 
    printf("%s \n", lFileType); 

    printf("lFilePath before scanf: "); 
    printf("%s \n", lFilePath); 

    printf("lFileName before scanf: "); 
    printf("%s \n", lFileName); 

    printf("lFileFinalPath before scanf: "); 
    printf("%s \n\n", lFileFinalPath); 

    printf("Bitte geben Sie den Namen der Pruefung an: \n\n"); 

    scanf("%s", &lFileName); 

    printf("\nlFileType after scanf: "); 
    printf("%s \n", lFileType); 

    printf("lFilePath after scanf: "); 
    printf("%s \n", lFilePath); 

    printf("lFileName after scanf: "); 
    printf("%s \n", lFileName); 

    printf("lFileFinalPath after scanf: "); 
    printf("%s \n\n", lFileFinalPath); 

    system("PAUSE"); 
    return 0; 
} 

Ожидаемый результат:

lFileType before scanf: .txt 
lFilePath before scanf: C:\Notenverwaltungssystem 
lFileName before scanf: 
lFileFinalPath before scanf: 
Bitte geben Sie den Namen der Pruefung an: 
Test 
lFileType after scanf: .txt 
lFilePath after scanf: C:\Notenverwaltungssystem 
lFileName after scanf: Test 
lFileFinalPath after scanf: 

Press any key to continue . . . 

Что я получаю в качестве выходного сигнала, когда я исполняю программка:

lFileType before scanf: .txt 
lFilePath before scanf: C:\Notenverwaltungssystem 
lFileName before scanf: 
lFileFinalPath before scanf: 

Bitte geben Sie den Namen der Pruefung an: 
Test 
lFileType after scanf: .txt 
lFilePath after scanf: st 
lFileName after scanf: Test 
lFileFinalPath after scanf: est 

Press any key to continue . . . 
+1

О размере буфера есть несколько ответов. Я хотел бы добавить, что 'scanf ("% s ", & lFileName)" можно изменить на 'scanf ("% s ", lFileName)', потому что 'lFileName' является адресом буфера, и нет необходимости в' '. – i486

ответ

7

При определении строки вроде этого:

char lFileName[] = ""; 

он имеет только один байт, выделенный ему (для завершение '\0'). Это эквивалентно следующему:

char lFileName[1] = ""; 

Если вы попытаетесь прочитать что-то в этой строке через scanf то вы получите переполнение буфера.

Измените это (и аналогичные определения), например.

char lFileName[PATH_MAX] = ""; 

(Обратите внимание, что вам может понадобиться #include <limits.h> вблизи начала вашего progaram для того, чтобы получить определение PATH_MAX).


Еще одна точка: при передаче строки в scanf вам не нужно разыменования его, так:

scanf("%s", &lFileName); 

должно быть просто:

scanf("%s", lFileName); 

(Для простых скалярных типов, таких как int или float, однако вам нужно передать указатель на переменную, что может ввести в заблуждение для людей, которые являются новыми для C.)

+1

А хорошо это для меня новенькое ... Спасибо за ваш быстрый ответ –

4

Все ваши массивы определены wi го размера, такого же, как и строка инициализации. Таким образом, по существу,

char lFileFinalPath[] = ""; 
char lFileName[] = ""; 

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

Кроме того, он всегда считается хорошей практикой, чтобы ограничить scanf() вход размером массива, где это возможно, как и для массива определяется как

char lFileType[128] = {0}; 

вы должны использовать формат scanf()

scanf("%127s", lFileType); 

во избежание переполнения буфера длинными входами.

+0

А я вижу ... Большое спасибо –

2
char lFileName[] = ""; 

Это просто выделить 1 байт памяти (для нулевого charecter '\ 0'), так как вы не указали размер массива. Функция scanf пытается сохранить строку ввода пользователя за границей массива, что приводит к ошибкам времени выполнения.

#define FILE_LEN 64;//select a size suitable for you. 
char lFileName[FILE_LEN] = ""; 

Другим способом является динамическое выделение памяти с помощью malloc() или calloc().

char *lFileName = NULL; 
lFileName = calloc(FILE_LEN,1); 

И всегда помните, чтобы освободить динамически выделенную память после ее использования с помощью free(). В противном случае это может привести к утечкам memmory.

free(lFileName);