c - 同时用 int 和 string 填充数组
问题描述
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
int main()
{
srand(time(NULL));
char hex[]="0123456789ABCDEF";
char seferNo[]="";
char numaraDeposu[100][6];
int j=0;
for (j=0;j<10;j++)
{
char seferNo[]="";
for (int i=0;i<4;i++)
{
int a;
a=(rand() % 15);
strncat(seferNo,&hex[a],1);
}
strcpy(numaraDeposu[j],seferNo);
printf("%s\n",numaraDeposu[j]);
}
}
这工作正常,但我想要 numaraDeposu 二维数组中的数字和字符串(代码)第一维包括 int,第二维包括我的随机代码(完美的英语)
1(随机码)2(随机码)3(随机码)4(随机码)这样
解决方案
如评论中所述,您char seferNo[]="";
是一个大小为 1 的数组,它只能包含空字符串 ( '\0'
) 并且仍被视为字符串。您的调用strncpy()
调用未定义的行为,因为没有足够的空间'\0'
来写入字符。
您可以使用 2D 数组执行您正在尝试的操作,并且无需包含string.h
. 您可以通过简单的字符操作来完成这一切stdio.h
sprintf()
,例如
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main (void) {
srand(time(NULL));
const char hex[]="0123456789ABCDEF";
char numaraDeposu[100][6] = {""};
for (int i = 0; i < 100; i++) {
numaraDeposu[i][0] = hex[rand() % 16];
sprintf (&numaraDeposu[i][1], "c%03d", rand()%1000);
printf ("%s\n", numaraDeposu[i]);
}
}
示例使用/输出
$ ./bin/numardeposu2D
Fc598
7c569
Ec247
1c451
Fc172
0c558
Bc501
0c462
Ec318
Ac396
2c742
0c304
4c146
...
当你需要一个持有不同类型的对象时使用结构体
每当您需要将不同类型作为单个对象进行协调时,您应该考虑struct
. 在这里,由于您将 2D 数组的每个字符串元素中的第一个字符限制为单个字符,char
因此并不完全需要。但是,它将为您在访问第一个字符和剩余代码的方式上提供更多的灵活性。
您可以使用一个简单的结构,例如:
typedef struct {
unsigned char hexnum;
char code[7];
} deposu_type;
选择Anunsigned char
只是为了使类型不同,但您可以同时使用char
两者。然后,您将声明一个结构数组并为数组中的每个结构填充每个成员,例如
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef struct {
unsigned char hexnum;
char code[7];
} deposu_type;
int main (void) {
srand(time(NULL));
const char hex[]="0123456789ABCDEF";
deposu_type numaraDeposu[100] = {{ .hexnum = 0 }};
for (int i = 0; i < 100; i++) {
numaraDeposu[i].hexnum = hex[rand() % 16];
sprintf (numaraDeposu[i].code, "c%03d", rand()%1000);
printf ("%c %s\n", numaraDeposu[i].hexnum, numaraDeposu[i].code);
}
}
示例使用/输出
hexnum
在和成员之间显示一个空格,code
以强调单独引用每个成员的便利性。
$ ./bin/numardeposu_struct
A c190
7 c329
D c955
7 c761
6 c968
D c781
8 c985
9 c449
7 c708
F c893
E c799
E c168
两种解决方案大致等效,但如果您的示例变得更复杂,使用struct
and 数组将是更简单的解决方案。struct
如果您还有其他问题,请仔细查看并告诉我。
根据需要为尽可能多的 numaraDeposu 动态分配存储
为了回应您关于如何为无限数量的对象分配存储空间的评论(我将其视为未知数字,因为您没有无限的可用内存),您将动态分配存储空间以保存所有numaraDeposu
使用malloc()
,calloc()
或realloc()
.
动态分配存储并不难。首先,为一些合理的数字结构分配存储空间,并将内存块的地址分配给指针变量。例如在这里,让我们为2
struct分配存储deposu_type
并将结果分配给我们的指针numaraDeposu
,例如
size_t available = 2, /* no. of struct available */
used = 0; /* no. of struct used */
/* allocate memory for initial (2) struct available */
deposu_type *numaraDeposu = malloc (available * sizeof *numaraDeposu);
if (numaraDeposu == NULL) { /* validate EVERY allocation */
perror ("malloc-numaraDeposu");
return 1;
}
(注意:您必须始终检查返回以验证您的分配成功或失败并处理任何失败)
您始终为分配保留两个计数器变量。available
计数器保存当前numaraDeposu
可以放入分配的内存块的used
数量,并跟踪您已填充(使用)的数量。当(used == available)
您重新分配更大的内存块并更新数量时available
。一个常见的增长模式是每次您需要更多可用数量时增加一倍,但您可以随意添加任意数量或任意数量。
一个为其分配存储的简单示例numaraDeposu
可以编写如下。使用这种方法,您可以根据numaraDeposu
需要分配任意数量的内存,直到用完物理内存:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef struct {
unsigned char hexnum;
char code[7];
} deposu_type;
int main (void) {
const char hex[]="0123456789ABCDEF";
size_t available = 2, /* no. of struct available */
used = 0; /* no. of struct used */
srand(time(NULL));
/* allocate memory for initial (2) struct available */
deposu_type *numaraDeposu = malloc (available * sizeof *numaraDeposu);
if (numaraDeposu == NULL) { /* validate EVERY allocation */
perror ("malloc-numaraDeposu");
return 1;
}
for (; used < 100; used++) {
if (used == available) { /* reallocate more when (used == available) */
/* always reallocate using temporary pointer */
void *tmp = realloc (numaraDeposu, 2 * available * sizeof *numaraDeposu);
if (!tmp) { /* valdate EVERY reallocation */
perror ("realloc-numaraDeposu");
break;
}
numaraDeposu = tmp; /* assign reallocated block to pointer */
available *= 2; /* updaate no. of struct available */
}
numaraDeposu[used].hexnum = hex[rand() % 16];
sprintf (numaraDeposu[used].code, "c%03d", rand()%1000);
printf ("%c %s\n", numaraDeposu[used].hexnum, numaraDeposu[used].code);
}
free (numaraDeposu); /* free all allocated memory */
}
内存使用/错误检查
在您编写的任何动态分配内存的代码中,对于分配的任何内存块,您有 2 个责任:(1)始终保留指向内存块起始地址的指针,(2)它可以在它不存在时被释放更需要。
您必须使用内存错误检查程序,以确保您不会尝试访问内存或写入超出/超出分配块的边界,尝试读取或基于未初始化值的条件跳转,最后确认释放所有分配的内存。
对于 Linuxvalgrind
是正常的选择。每个平台都有类似的内存检查器。它们都易于使用,只需通过它运行您的程序即可。
$ valgrind ./bin/numardeposu_struct_dyn
==13231== Memcheck, a memory error detector
==13231== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==13231== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==13231== Command: ./bin/numardeposu_struct_dyn
==13231==
C c582
A c524
4 c742
1 c697
5 c890
...
6 c509
A c079
2 c511
0 c770
==13231==
==13231== HEAP SUMMARY:
==13231== in use at exit: 0 bytes in 0 blocks
==13231== total heap usage: 8 allocs, 8 frees, 3,056 bytes allocated
==13231==
==13231== All heap blocks were freed -- no leaks are possible
==13231==
==13231== For counts of detected and suppressed errors, rerun with: -v
==13231== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
始终确认您已释放所有已分配的内存并且没有内存错误。
如果您还有其他问题,请告诉我。
推荐阅读
- docker - 在构建 docker 容器时使用本地依赖项
- ios - 如何将颜色保存到领域并在其他视图控制器中显示颜色?
- sql - 将非规范化 csv 文件导入生产数据库表
- android - 在 Android 上使用 libgdx 加载大量点模型需要大量时间
- java - 通过 Android PDFDocument 生成的 PDF 尺寸太大。在使用 pdfbox 时,它会在输出中剪切图像
- javascript - 如何根据其他标签数组对带有标签的对象数组进行排序?
- php - 语法错误或访问冲突:1066 不是唯一的表/别名:
- javascript - 使用 Append 添加的项目无法被 querySelectorAll 识别
- jquery - 选择 2 Webpack-encore
- javascript - 在javascript Themezy模板中向地图添加标记