我是C语言新手,我用这个语句分配了内存。
patientptr = (char*) calloc (118, sizeof (char));
然后我用这个来分配数据(这是函数的一部分)。
char name[51];
int age;
char agestr[3];
char infectiondate [11];
char address[51];
char *patientptr;
printf("\nEnter the patient name (50 characters at maximum): ");
scanf ("%50s", name);
*patientptr = name;
printf("Enter the patient age: ");
scanf ("%d", &age);
sprintf (agestr, "%2d", age);
*(patientptr + 51) = agestr;
printf("Enter the patient date of infection (in form of dd/mm/year): ");
*(patientptr + 54) = scanf ("%10d", infectiondate);
printf("Enter the patient address (50 characters at maximum): ");
*(patientptr + 65) = scanf ("%50s", address);
*(ptrsptr+patientsnum-1) = patientptr;
printf ("\nPatient added.\n");
一切都很顺利 除了在 "输入病人地址 "这一行之后 "行后,它直接打印出 "添加的病人 "行,而没有等待扫描地址,输出是这样的:
Enter the patient name (50 characters at maximum): ahmed
Enter the patient age: 20
Enter the patient date of infection (in form of dd/mm/year): 10/10/2020
Enter the patient address (50 characters at maximum):
Patient added.
我分配的内存有问题吗?
你很可能已经使用了 calloc
来分配一些内存,但检查这个片段。
char *patientptr;
printf("\nEnter the patient name (50 characters at maximum): ");
scanf ("%50s", name);
*patientptr = name;
第一行 影子 无论如何 patientptr
是用一个未初始化的指针,因此最后一行是未定义的行为 (patientptr
现在指向某个任意的地址)。) 此时,所有的赌注都被取消了。任何 是可以的。
修正后再试。
此外,它 样子 就像你相信的那样。
*(patientptr + 51) = agestr;
是将C字符串从一个地方复制到另一个地方的方法。实际上,这将试图把C字符串的 agestr
指针 的值转化为内存位置的单个字符 &(patientptr[51])
我可能应该警告你这个问题
你需要看看 strcpy
为这一点,类似的东西。
strcpy(patientptr + 51, agestr);
但是,如果你想做用户输入, 通常是一个好主意,绕过限制的问题 scanf
. 它 确实如此。 毕竟,站在 "扫描格式化 "的立场上,几乎没有什么是 较少 比用户输入的格式化。
我有一个最喜欢用的函数,如下图所示,以及修改你自己的代码来使用它(同时使用该函数的 和 并根据你的情况做了很多其他的验证)。)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
// Bullet-proof line input function.
#define OK 0
#define NO_INPUT 1
#define TOO_LONG 2
static int getLine (char *prmpt, char *buff, size_t sz) {
int ch, extra;
// Get line with buffer overrun protection.
if (prmpt != NULL) {
printf ("%s", prmpt);
fflush (stdout);
}
if (fgets (buff, sz, stdin) == NULL)
return NO_INPUT;
// If it was too long, there'll be no newline. In that case, we flush
// to end of line so that excess doesn't affect the next call.
if (buff[strlen(buff)-1] != '\n') {
extra = 0;
while (((ch = getchar()) != '\n') && (ch != EOF))
extra = 1;
return (extra == 1) ? TOO_LONG : OK;
}
// Otherwise remove newline and give string back to caller.
buff[strlen(buff)-1] = '\0';
return OK;
}
// Ensure a character array is non-empty and all digits.
int checkDigits(char *arr, size_t sz) {
if (sz == 0) {
return 0;
}
while (sz-- > 0) {
if (! isdigit(*arr++)) {
return 0;
}
}
return 1;
}
// Get customer data line, return NULL if okay, error if not.
// Output record must be long enough for format string below
// and a one-character end-string marker.
static char *getPatientData(char *patientData) {
// Keep this format string in sync with field sizes below.
static char *fmtString = "%-50.50s" "%3d" "%-10.10s" "%-50.50s";
char name[51];
char ageStr[4];
char infectionDate[11];
char address[51];
if (getLine("Patient name: ", name, sizeof(name)) != OK) {
return "Error getting name.";
}
if (getLine("Patient age: ", ageStr, sizeof(ageStr)) != OK) {
return "Error getting age.";
}
if (! checkDigits(ageStr, strlen(ageStr))) {
return "Error, age contains non-digit data.";
}
int age = atoi(ageStr);
// Further age sanity checking, if desired. Example: ensure <= 150.
if (getLine("Infection date (dd/mm/yyyy): ", infectionDate, sizeof(infectionDate)) != OK) {
return "Error getting infection date.";
}
if (
strlen(infectionDate) != 10
|| infectionDate[2] != '/'
|| infectionDate[5] != '/'
|| ! checkDigits(infectionDate, 2)
|| ! checkDigits(infectionDate + 3, 2)
|| ! checkDigits(infectionDate + 6, 4)
) {
return "Error, incorrect format.";
}
// Further checking if desired. Example: valid year/month/day combo.
if (getLine("Patient address: ", address, sizeof(address)) != OK) {
return "Error getting address.";
}
sprintf(patientData, fmtString, name, age, infectionDate, address);
return NULL;
}
int main(void) {
char *patientPtr = malloc (50 + 3 + 10 + 50 + 1);
char *result = getPatientData(patientPtr);
if (result != NULL) {
printf("*** %s\n", result);
return 1;
}
printf("Got '%s'\n", patientPtr);
return 0;
}
下面是一个运行示例。
Patient name: Pax Diablo
Patient age: 55
Infection date (dd/mm/yyyy): 25/05/2020
Patient address: No fixed abode
Got 'Pax Diablo 5525/05/2020No fixed abode '