#include<stdlib.h>
#include<stdio.h>
#include<time.h>
#include<string.h>
char *GetTodayDate()
{
char *buffer;
time_t t = time(NULL);
struct tm tm = *localtime(&t);
char monBuffer[3] ;
char dayBuffer[3];
char yearBuffer[5];
sprintf(monBuffer, "%02d", tm.tm_mon + 1);
sprintf(dayBuffer, "%02d", tm.tm_mday);
sprintf(yearBuffer, "%d", tm.tm_year + 1900);
strcat(buffer, monBuffer);
strcat(buffer, "/");
strcat(buffer, dayBuffer);
strcat(buffer, "/");
strcat(buffer, yearBuffer);
return buffer;
}
int main()
{
char *today;
sprintf(today,"%s",GetTodayDate());
// I want to print the today string here to check, please give me proper statement here
return 0;
}
我在程序中遇到分段错误,我想将dayBuffer,monBuffer,yearBuffer缓冲区存储到单个缓冲区中,这样我就可以将此缓冲区传递给另一个程序。我想将此缓冲区返回给另一个程序
答案 0 :(得分:3)
你甚至没有分配buffer
所以这是未定义的行为,写在未分配/随机区域。
char *buffer;
在这种情况下,可以安全地替换为
char *buffer = malloc(11); buffer[0]= '\0';
这是保持YYYY / MM / DD日期所需的大小,并初始化为0,因此第一个strcat
正常工作(否则会出现另一种未定义行为的情况)
我会在一次sprintf
调用中执行此操作,但没有所有临时缓冲区和strcat
调用:
char *buffer = malloc(11); /* no need to initialize it beforehand */
sprintf(buffer, "%02d/%02d/%d", tm.tm_mon + 1, tm.tm_mday, tm.tm_year + 1900);
(因为你返回 buffer
,你不能使用char buffer[11];
,即使它很有吸引力,因为范围仅限于当前例程)
除此之外:main()
中的同一问题。你是(再次)写在未定义的内存中。既然你分配了内存就行了:
int main()
{
char *today = GetTodayDate();
printf("The date is %s\n",today);
free(today); // free memory, even if it's not really necessary here, you're quitting the program
return 0;
}
答案 1 :(得分:3)
strcat(buffer,monBuffer);
您还没有为buffer
分配任何内存,因此您会遇到段错误,因为buffer
没有指向从堆分配的任何可写内存块来保存您的数据。使用malloc
为您的字符串分配一些内存。并且不要忘记将这些内存返回到free
这样的堆:
char *GetTodayDate()
{
char *buffer = malloc (MAX_DT_STRING_LEN);
/* ... */
*buffer = 0;
然后在main()
:
char *today = GetTodayDate();
printf ("%s", today);
free (today);
优良作法是初始化指针并检查从malloc
和其他可能分配内存的例程返回的值NULL
。
您也可以预先分配缓冲区并将指针传递给GetTodayDate()
。
此处MAX_DT_STRING_LEN
是缓冲区的长度。为缓冲区选择任意合理的长度,以便能够保存最大可能的日期/时间字符串。
答案 2 :(得分:0)
正如其他人所指出的那样,你必须分配内存。那么问题就变成了#34;谁应该分配内存&#34;。请允许我提出三种相当标准的方式来回答这个问题及其缺点和优点。
一种可能性是让来电者分配内存 :(我还添加了错误报告,因为这是我比其他两个人更喜欢这种方法的原因之一,请随意忽略它。)
#include<stdlib.h>
#include<stdio.h>
#include<time.h>
#include<string.h>
#define DATE_SIZE 12
enum error_codes {OK = 0, ERROR = -1};
// You could have multiple error codes
int GetTodayDate(char *buffer);
int main()
{
char *today = malloc(DATE_SIZE);
int err = GetTodayDate(today);
if(err == OK)
printf("Today is %s\n", today);
else
printf("Error getting date\n")
free(today);
return 0;
}
int GetTodayDate(char *buffer)
{
/* Get the info */
time_t t = time(NULL);
struct tm tm = *localtime(&t);
/* Convert it to strings */
char monBuffer[3] ;
char dayBuffer[3];
char yearBuffer[5];
sprintf(monBuffer, "%02d", tm.tm_mon + 1);
sprintf(dayBuffer, "%02d", tm.tm_mday);
sprintf(yearBuffer, "%d", tm.tm_year + 1900);
if( something_went_wrong_here)
return -1;
/* Put in the buffer */
*buffer = '\0'; // same as doing buffer[0] = '\0'; but is more C-stylish
strcat(buffer, monBuffer);
strcat(buffer, "/");
strcat(buffer, dayBuffer);
strcat(buffer, "/");
strcat(buffer, yearBuffer);
return 0; // To indicate success,
}
然后另一个选项,它不是THREAD SAFE但被许多C标准库函数使用,它将允许您调用函数返回字符串而不用担心内存管理如下:它使用 static函数GetTodayDate中的字符数组。这使得数组虽然充当局部变量,但在函数返回后仍然存在(静态局部变量实际上是一个只能在函数内访问的全局变量)。
#include<stdlib.h>
#include<stdio.h>
#include<time.h>
#include<string.h>
#define DATE_SIZE 12
char *GetTodayDate();
int main()
{
// Easier to use but has drawbacks
printf("Today is %s", GetTodayDate());
return 0;
}
char *GetTodayDate()
{
/* Get the info */
time_t t = time(NULL);
struct tm tm = *localtime(&t);
/* Convert it to strings */
char monBuffer[3] ;
char dayBuffer[3];
char yearBuffer[5];
sprintf(monBuffer, "%02d", tm.tm_mon + 1);
sprintf(dayBuffer, "%02d", tm.tm_mday);
sprintf(yearBuffer, "%d", tm.tm_year + 1900);
/* Put in the buffer */
static char buffer[DATE_SIZE];
buffer[0] = '\0';
strcat(buffer, monBuffer);
strcat(buffer, "/");
strcat(buffer, dayBuffer);
strcat(buffer, "/");
strcat(buffer, yearBuffer);
return buffer;
}
这也有一个缺点,如果你想在以后使用该值,你必须使用strcpy()复制它。但是你可以看到使用这个函数要简单得多。
第三个选项是让 GetTodayDate分配内存,这样做的好处是它知道要分配多少内存,从而使用户不必知道该细节。它的缺点是,由于客户端没有分配内存,他可能有更多机会忘记释放内存。
#include<stdlib.h>
#include<stdio.h>
#include<time.h>
#include<string.h>
#define DATE_SIZE 12
int GetTodayDate(char *buffer);
int main()
{
char *today = GetTodayDate();
printf("Today is %s", today);
// Easier to forget to do if
// we're not the one who wrote GetTodayDate
free(today);
return 0;
}
char *GetTodayDate()
{
/* Get the info */
time_t t = time(NULL);
struct tm tm = *localtime(&t);
/* Convert it to strings */
char monBuffer[3] ;
char dayBuffer[3];
char yearBuffer[5];
sprintf(monBuffer, "%02d", tm.tm_mon + 1);
sprintf(dayBuffer, "%02d", tm.tm_mday);
sprintf(yearBuffer, "%d", tm.tm_year + 1900);
/* Put in the buffer */
char *buffer = malloc(DATE_SIZE);
buffer[0] = '\0';
strcat(buffer, monBuffer);
strcat(buffer, "/");
strcat(buffer, dayBuffer);
strcat(buffer, "/");
strcat(buffer, yearBuffer);
return buffer;
}
我个人更喜欢第一个,因为它允许我使用返回值进行错误报告。此外,许多C标准库函数都以这种方式工作:调用函数并告诉它(通过参数)将您请求的信息放在何处。当您希望函数在不复制的情况下返回多个内容时,这尤其有用。
struct BigStruct bs;
// get me this info and here's
// where you're going to put said info.
if(get_BigStruct(&bs)){
printf("could not get info\n");
return ERROR;
}
printf("field1 %d\n", bs.field1);
但我离题了,关键是我最喜欢第一个因为 1)错误报告 2)分配和解除分配在同一地点完成 3)常见的C方式&#34;告诉我这些信息,以及您将要放置它的地方&#34;。