scanf 更改其他字符串的值

scanf changes values from other strings

我主要用 Java 开发软件,但目前我正在用 C 尝试一些东西,但遇到了一个奇怪的问题。

我使用 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 . . .

当你这样定义一个字符串时:

char lFileName[] = "";

它只分配了一个字节(用于终止'[=15=]')。相当于:

char lFileName[1] = "";

如果您尝试通过 scanf 将某些内容读入此字符串,则会出现缓冲区溢出。

将此(和类似定义)更改为例如

char lFileName[PATH_MAX] = "";

(请注意,您可能需要在程序开始附近使用 #include <limits.h> 才能获得 PATH_MAX 的定义)。


还有一点:将字符串传递给 scanf 时,您不需要取消引用它,因此:

scanf( "%s", &lFileName );

应该是:

scanf( "%s", lFileName );

(对于诸如 intfloat 之类的简单标量类型,您确实需要将指针传递给变量,这对于 C 的新手来说可能会造成混淆。)

你所有的数组都定义了与提供的初始化字符串相同的大小。所以,基本上,

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

长度为 1,这是您不想要的。如果您希望数组在程序的后面部分保持不同的长度,您可能需要明确提供大小。

此外,尽可能通过数组大小限制 scanf() 输入始终被认为是一种好习惯,例如对于定义为

的数组
char lFileType[128] = {0};

你应该使用 scanf() 格式

scanf("%127s", lFileType);

以避免因较长的输入而导致缓冲区溢出的可能性。

char lFileName[] = ""; 

这只是分配了 1 个字节的内存(用于空字符'\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() 后释放动态分配的内存。否则可能会导致内存泄漏。

free(lFileName);