【发布时间】:2018-03-18 10:50:23
【问题描述】:
我有一个小程序,可以将 12 小时制转换为 24 小时制。
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <limits.h>
#include <stdbool.h>
int get_tokens(char* buf, char *fields[], char *sep){
char* ptr= (char*)malloc((10*sizeof(char))+1);
strncpy(ptr, buf, 10);
*(ptr+10)='\0';
int num_f=0;
while((fields[num_f] = strtok(ptr,sep)) != NULL ){
ptr = NULL;
num_f++;
}
return num_f;
}
char* timeConversion(char* s) {
char *fields[3];
int num_f=0;
char *ptr = (char*) malloc(100*sizeof(char));
int hour=0;
get_tokens(s, fields, ":");
if(strstr(s,"PM")){
hour=atoi(fields[0])+12;
}
else{
hour=atoi(fields[0]);
}
snprintf(ptr, 9, "%d:%s:%s" ,hour,fields[1],fields[2]);
return ptr;
}
int main() {
char* s = (char *)malloc(100 * sizeof(char));
scanf("%s", s);
char* result = timeConversion(s);
printf("%s\n", result);
return 0;
}
我在 timeConversion 函数返回后立即看到“堆栈粉碎”。 我知道代码的逻辑有效,但无法弄清楚堆栈粉碎。
【问题讨论】:
-
scanf("%s", s);至少有 3 个问题。 -
不要投射
malloc(),乘以sizeof(char)是没有意义的,因为它是1。 -
不要使用
strncpy。这是可憎的。 -
@CIsForCookies 不,
&s是错误的。 1) 确实是潜在的缓冲区溢出(没有长度限制)。 2) 不检查返回值以确保scanf成功读取字符串。 3) 完全使用scanf进行用户输入。scanf%s特别不是基于行的;它将跳过任何初始空白,然后读取一系列非空白字符,这对于程序员(该行的其余部分(包括最后的换行符)保留在输入缓冲区中)和用户(如果您只是按 Enter 键,程序似乎会挂起)。 -
@Zebrafish 如果您确实需要
strncpy的功能,可以使用memcpy和memset的组合。但是,如果您只想执行有界字符串复制(这不是strncpy所做的,尽管它的名称),最简单的方法是snprintf。
标签: c pointers char stack-smash