如何在C语言中使用'url('result/4star/${random}.jpg}')'函数?

How to use the `url('outcome/4star/${random}.jpg')` function in C?

提问人:soph 提问时间:8/7/2023 最后编辑:Okasoph 更新时间:8/8/2023 访问量:66

问:

这是我现在的代码:

srand(time(NULL));   
int photo = rand()%((3+1)-1) + 1; 
fp_r = fopen("ascii_art/Animals/${photo}", "r");

我想做('result/4star/${random}.jpg'),但只是用C语言。我能做些什么?

C 字符串 文件 string-interpolation

评论

0赞 tshiono 8/7/2023
你可能想说.fopen(sprintf("ascii_art/Animals/%d", photo), "r");
0赞 Allan Wind 8/7/2023
@tshiono 这不起作用,因为返回一个 int;插值字符串是第一个参数。sprintf()
0赞 tshiono 8/7/2023
@AllanWind你是对的。我与其他语言混淆了。:)
2赞 Jonathan Leffler 8/7/2023
标题和正文谈论;C 代码尝试使用 .你到底想要哪个?你有多少张照片?它们是按顺序编号还是有间隙?您需要添加后缀吗?你为什么要写作而不是仅仅写作?你真的只有三张照片吗?outcome/4star/${random}.jpgascii_art/Animals/${photo}.jpg((3 + 1) - 1)3
0赞 Allan Wind 8/8/2023
你得到了两个很好的答案。请单击它旁边的复选标记来接受最好的一个,以便我们知道您已设置完毕。

答:

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_t2^8 - 1 = 2553

#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()photopathmalloc()

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 允许您确定缓冲区必须有多大 - 如果您想要动态分配它:0snprintf

#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
好答案。您为什么将 % 从 更改为 ?310
1赞 Oka 8/7/2023
@AllanWind 对于范围 [1, 3],不可能获得根据输入不一致截断输出的示例。snprintf