简体   繁体   English

scanf更改其他字符串中的值

[英]scanf changes values from other strings

I mainly develop software in Java, but currently I'm trying some stuff in C and I got stuck on a strange problem. 我主要使用Java开发软件,但是目前我正在尝试使用C进行一些开发,但遇到了一个奇怪的问题。

I use the scanf() method to change the value from a string, but scanf() doesn't change just the value from the parameterized string it changes also the value from other strings. 我使用scanf()方法来更改字符串中的值,但是scanf()不仅会更改参数化字符串中的值,还会更改其他字符串中的值。

Now my question: am I just spoiled from the developer-friendly Java and I'm too dumb to use it right? 现在我的问题是:我只是被对开发人员友好的Java宠坏了,我太笨了,无法正确使用它吗? I don't see where I'm doing the mistake. 我看不到我在哪里做错。

#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;
}

Expected output: 预期产量:

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 . . .

What I get as output when I execute the programm: 执行程序时得到的输出是:

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 . . .

When you define a string like this: 当您定义这样的字符串时:

char lFileName[] = "";

it only has one byte allocated to it (for the terminating '\\0' ). 它仅分配了一个字节(用于终止'\\0' )。 It is equivalent to this: 等效于:

char lFileName[1] = "";

If you try to read something into this string via scanf then you will get a buffer overflow. 如果您尝试通过scanf读取一些内容到该字符串中,则将导致缓冲区溢出。

Change this (and similar definitions) to eg 将此(和类似的定义)更改为

char lFileName[PATH_MAX] = "";

(Note that you may need #include <limits.h> near the start of your progaram in order to get the definition of PATH_MAX ). (请注意,您可能需要在progaram开头附近添加#include <limits.h>才能获取PATH_MAX的定义)。


One further point: when passing a string to scanf you don't need to dereference it, so: 还有一点:将字符串传递给scanf您无需取消引用它,因此:

 scanf( "%s", &lFileName ); 

should just be: 应该只是:

 scanf( "%s", lFileName ); 

(For simple scalar types such as int or float however you do need to pass a pointer to the variable, which can be confusing for people who are new to C.) (但是对于简单的标量类型,例如intfloat您确实需要传递一个指向变量的指针,这对于C语言新手来说可能会造成混淆。)

All your arrays are defined with a size same as the supplied initializer string. 您定义的所有数组的大小都与提供的初始化程序字符串相同。 So, essentially, 所以本质上

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

are having length 1, which is what you don't want. 长度为1,这是您不想要的。 You may want to supply the size explicitly, if you want the arrays to hold a different length at a later part of the program. 如果希望数组在程序的后面部分保留不同的长度,则可能需要显式提供大小。

Also, it is always considered a good practice to limit the scanf() input by the array size, wherever possible, like for an array defined like 同样,始终认为最好的做法是,在可能的情况下,通过数组大小限制scanf()输入,例如对于定义如下的数组:

char lFileType[128] = {0};

you should use a scanf() format 您应该使用scanf()格式

scanf("%127s", lFileType);

to avoid the possibility of buffer overflow by lengthier inputs. 避免由于较长的输入而导致缓冲区溢出的可能性。

char lFileName[] = ""; 

This simply allocate 1 byte of memory(for the null charecter '\\0'), since you have not specified the size of the array. 这只是分配1字节的内存(用于空字符'\\ 0'),因为您尚未指定数组的大小。 The scanf function try to store the user input string beyond the array boundary, leading to run time errors. scanf函数尝试将用户输入的字符串存储在数组边界之外,从而导致运行时错误。

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

Another way is to dynamically allocate memory using malloc() or calloc(). 另一种方法是使用malloc()或calloc()动态分配内存。

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

And always remember to free the dynamically allocated memory after its usage using free(). 并且始终记得在使用free()后释放动态分配的内存。 Otherwise it may lead to memmory leaks. 否则可能导致内存泄漏。

free(lFileName);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM