我主要使用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 . . .
答案 0 :(得分:7)
定义这样的字符串时:
char lFileName[] = "";
它只分配了一个字节(用于终止'\0'
)。它相当于:
char lFileName[1] = "";
如果您尝试通过scanf
读取此字符串中的内容,则会出现缓冲区溢出。
将此(及类似定义)更改为例如
char lFileName[PATH_MAX] = "";
(请注意,在progaram开头附近可能需要#include <limits.h>
才能获得PATH_MAX
的定义。
scanf
时,您无需取消引用它,因此:
scanf( "%s", &lFileName );
应该是:
scanf( "%s", lFileName );
(对于简单的标量类型,例如int
或float
,但是您需要传递一个指向变量的指针,这对于C新手来说可能会造成混淆。)
答案 1 :(得分:4)
所有数组的定义大小与提供的初始化字符串相同。所以,基本上,
char lFileFinalPath[] = "";
char lFileName[] = "";
长度为1,这是你不想要的。如果希望数组在程序的后续部分保持不同的长度,则可能需要显式提供大小。
此外,在任何可能的情况下,将scanf()
输入限制为数组大小始终被认为是一种好习惯,例如像
char lFileType[128] = {0};
您应该使用scanf()
格式
scanf("%127s", lFileType);
以避免较长输入导致缓冲区溢出的可能性。
答案 2 :(得分:2)
char lFileName[] = "";
这只是分配1个字节的内存(对于null charecter&#39; \ 0&#39;),因为你没有指定数组的大小。 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);