C中的sprintf给出了错误的输出

问题描述 投票:1回答:6
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define MAX_STRING  20

char *getFirstName() {
    char firstName[MAX_STRING];
    printf("Please enter your first name: ");
    gets(firstName);
    return (firstName);
}

char *getLastName() {
    char lastName[MAX_STRING];

    printf("Please enter your last name: ");
    gets(lastName);
    return (lastName);
}

char *getNickName() {
    char nickName[MAX_STRING];
    printf("Please enter your nick name: ");
    gets(nickName);
    return (nickName);
}

char *getCompleteName(const char *firstName,
                      const char *lastName,
                      const char *nickName) {
    char *completeName;
    sprintf(completeName, "%s \"%s\" %s", firstName, nickName, lastName);
    return (completeName);
}

int main() {
    char *firstName;
    char *lastName;
    char *nickName;
    char *completeName;

    firstName   = getFirstName();
    lastName    = getLastName();
    nickName    = getNickName();

    completeName = getCompleteName(firstName, lastName, nickName);
    printf("Hello %s.\n", completeName);
    return (EXIT_SUCCESS);
}

代码有什么问题。它总是在所有三个变量firstNamelastNamenickName中打印昵称。

输出:]

它必须显示完整的名称。我认为错误在getCompleteName函数中。

c printf
6个回答
1
投票

我建议使用char数组并将它们作为参数传递给您的函数。如果char firstName[MAX_STRING];终止,你本地数组getFirstName超出范围。在getFirstName终止并且指向变量的指针未定义的行为之后,此变量不再可访问。

#include <stdio.h>

#define MAX_STRING 10

void getFirstName( char *firstName )
{
    printf("Please enter your first name: ");
    fflush( stdout );
    fgets( firstName, MAX_STRING, stdin );
}

void getLastName( char *lastName )
{
  printf("Please enter your last name: ");
  fflush( stdout );
  fgets( lastName, MAX_STRING, stdin );
}

void getNickName( char *nickName )
{
    printf("Please enter your nick name: ");
    fflush( stdout );
    fgets( nickName, MAX_STRING, stdin );
}

void getCompleteName (
         char*          completeName,
         const char*    firstName,
         const char*    lastName,
         const char*    nickName)
{
  sprintf(completeName,"%s \"%s\" %s",firstName,nickName,lastName);
}

int main ()
{
  char firstName[MAX_STRING];
  char lastName[MAX_STRING];
  char nickName[MAX_STRING];
  char completeName[MAX_STRING*3+10];

  getFirstName( firstName  );
  getLastName( lastName );
  getNickName( nickName );

  getCompleteName( completeName, firstName, lastName, nickName );
  printf("Hello %s.\n",completeName);
  return(EXIT_SUCCESS);
} 

除了这个使用fgets而不是gets,因为qazxsw poi检查要读取的最大字符数(包括最终的空字符)请参阅fgets


2
投票

在函数How to read from stdin with fgets()?中,在将内容组合到其中之前,必须为getCompleteName分配内存:

completeName

笔记:

  • 调用函数将负责释放内存。这种分配方案实用但容易出错,已知会在草率实现中导致内存泄漏。
  • 其余代码也有同样的问题:指针必须指向调用函数中已分配的内存,静态数组或本地数组。
  • 你不能使用char *getCompleteName(const char *firstName, const char *lastName, const char *nickName) { size_t size = strlen(firstName) + strlen(lastName) + strlen(nickName) + 5; char *completeName = malloc(size); if (completeName) { snprintf(completeName, size, "%s \"%s\" %s", firstName, nickName, lastName); } return completeName; } ,它不能安全使用。使用gets()并去除拖尾换行符。

1
投票
fgets()

completeName指向哪里?由于使用了不确定的值,这会调用未定义的行为。

你应该提供静态存储,例如同

char* completeName;
sprintf(completeName,"%s \"%s\" %s",firstName,nickName,lastName);

下一个问题是自动变量,例如函数返回时超出范围。您应该使数组静态以避免这种情况。


1
投票

1)你不能在堆栈上使用数组 - 也许这可能会更好

static char completeName[128];

2)使用它

 void getDetail(const char * const prompt, char *detail, int maxSize)
 {
    printf("%s:", prompt);
    fflush(stdout); // Gives the user a chance to set it
    if (fgets(detail, maxSize, stdin) == NULL) {
       detail[0] = 0; // EOF - Empty string
    }
    else
    {
       // Strip off new line
       size_t l = strlen(detail);
       if (detail[l - 1] == '\n') detail[l - 1] = 0;
    }

 }

3)现在制作完整的名称

char firstName[MAX_SIZE];
getDetail("Please enter you first name", firstName, MAX_SIZE);


... ditto for the others

...如果你希望把它放入一个函数传递到它的数组。但在这个例子中似乎并不值得

4)打印完整名称

char completeName{MAX_SIZE * 3 + 10]; // Cannot be bothered to work out the exta but that will be enough
sprintf(completeName,"%s \"%s\" %s",firstName,nickName,lastName);

0
投票

指针变量printf("Complete name is :%s\n", completeName); 未初始化,导致C标准调用未识别的行为。任何事情都可能发生。

您还尝试从函数中返回数组。它们被转换为指向每个数组中第一个元素的指针,并返回该指针。但由于数组是一个局部变量,所谓的“存储类自动”,它会在函数返回时消失。 Rhe记忆可以重复用于其他事情,但指针仍然指向内存中的那个位置。同样,行为未定义。


0
投票

使用char和fgets数组而不是gets。顺便说一下,你的初始代码在Ubuntu 15.10和gcc(Ubuntu 5.2.1-22ubuntu2)5.2.1 20151010上产生了分段错误。

SK

© www.soinside.com 2019 - 2024. All rights reserved.