提问人:soph 提问时间:8/7/2023 最后编辑:Okasoph 更新时间:8/8/2023 访问量:66
如何在C语言中使用'url('result/4star/${random}.jpg}')'函数?
How to use the `url('outcome/4star/${random}.jpg')` function in C?
问:
这是我现在的代码:
srand(time(NULL));
int photo = rand()%((3+1)-1) + 1;
fp_r = fopen("ascii_art/Animals/${photo}", "r");
我想做('result/4star/${random}.jpg'),但只是用C语言。我能做些什么?
答:
1赞
Allan Wind
8/7/2023
#1
我可能会做:
// ...
#include <string.h>
int main(void) {
srand(time(NULL));
char path[] = "ascii_art/Animals/?.jpg";
path[strcspn(path, "?")] = '1' + rand() % 3;
fp_r = fopen(path, "r");
}
更普遍的办法是按照@tshiono的建议使用。最简单的方法是在编译时对所需的最大字节数进行硬编码。为此,最好使用 stdint.h 类型中的整数类型之一,如您所知,它的最大值是,因此您最多需要字节:sprintf()
uint8_t
2^8 - 1 = 255
3
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define TEMPLATE "ascii_art/Animals/%" PRIu8 ".jpg"
int main(void) {
srand(time(NULL));
char path[sizeof(TEMPLATE) - sizeof(PRIu8) + 3];
sprintf(path, TEMPLATE, (uint8_t) (rand() % 3 + 1));
fp_r = fopen(path, "r);
}
或者,使用或写入运行时所需的函数计数字节数。 现在是一个可变长度数组 (VLA),或者您必须将其堆分配给 or 朋友。log10()
photo
path
malloc()
0赞
Oka
8/7/2023
#2
C 不支持语言级别1 的字符串插值。您必须使用函数,并手动管理缓冲区。
snprintf
对于执行字符串插值很有用,因为在成功时,它会返回完全呈现结果字符串所需的字符数减去以 null 结尾的字节。
对于固定缓冲区,这样可以很容易地检测字符串何时被剪短。考虑以下(人为的)示例,其中 1/10 的几率生成的字符串对于缓冲区来说太长。
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void)
{
srand((unsigned) time(NULL));
char filename[24];
int n = (rand() % 10) + 1;
errno = 0;
int rc = snprintf(filename, sizeof filename, "ascii_art/Animals/%d.jpg", n);
if (rc < 0 || rc >= sizeof filename) {
if (errno)
perror("snprintf");
else
fprintf(stderr, "String truncation occurred.\n");
return EXIT_FAILURE;
}
printf("Generated path: <%s>\n", filename);
FILE *file = fopen(filename, "r");
if (file) {
/* ... */
fclose(file);
}
}
$ ./a.out
Generated path: <ascii_art/Animals/2.jpg>
$ ./a.out
String truncation occurred.
这样做的第二个好处是,传递大小 to 允许您确定缓冲区必须有多大 - 如果您想要动态分配它:0
snprintf
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define PATH_TEMPLATE "ascii_art/Animals/%d.jpg"
int main(void)
{
srand((unsigned) time(NULL));
int n = (rand() % 10) + 1;
int len = snprintf(NULL, 0, PATH_TEMPLATE, n);
if (-1 == len) {
perror("snprintf");
return EXIT_FAILURE;
}
char *filename = malloc(len + 1);
if (!filename || -1 == sprintf(filename, PATH_TEMPLATE, n)) {
perror("failure to dynamically allocate filename");
return EXIT_FAILURE;
}
printf("Generated path: <%s>\n", filename);
FILE *file = fopen(filename, "r");
if (file) {
/* ... */
fclose(file);
}
free(filename);
}
$ ./a.out
Generated path: <ascii_art/Animals/3.jpg>
$ ./a.out
Generated path: <ascii_art/Animals/10.jpg>
作为替代方案,asprintf
是一个 GNU(和 BSD)函数,它的作用与前面的例子几乎完全相同:调整大小并动态分配字符串。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void)
{
srand((unsigned) time(NULL));
char *filename = NULL;
int n = (rand() % 10) + 1;
if (-1 == asprintf(&filename, "ascii_art/Animals/%d.jpg", n)) {
perror("asprintf");
return EXIT_FAILURE;
}
printf("Generated path: <%s>\n", filename);
FILE *file = fopen(filename, "r");
if (file) {
/* ... */
fclose(file);
}
free(filename);
}
$ ./a.out
Generated path: <ascii_art/Animals/6.jpg>
$ ./a.out
Generated path: <ascii_art/Animals/4.jpg>
1. 不包括字符串文字连接。
评论
0赞
Allan Wind
8/7/2023
好答案。您为什么将 % 从 更改为 ?3
10
1赞
Oka
8/7/2023
@AllanWind 对于范围 [1, 3],不可能获得根据输入不一致截断输出的示例。snprintf
评论
fopen(sprintf("ascii_art/Animals/%d", photo), "r");
sprintf()
outcome/4star/${random}.jpg
ascii_art/Animals/${photo}
.jpg
((3 + 1) - 1)
3