在文件名中添加数字

时间:2019-05-31 14:32:32

标签: c string scope undefined-behavior

我想将数据存储在不同的文件中。因此,我想按以下方式创建文件:data_1.logdata_2.log,...,data_N.log。附录.log不是必需的,但会很好。到目前为止,我所有的方法都失败了。这是一个可能与我需要的样品接近的样品:

#include <stdio.h>
#include <string.h>

char get_file_name(int k){ 
    int i, j;
    char s1[100] = "logs/data_";
    char s2[100];
    snprintf(s2, 100, "%d", k);
    for(i = 0; s1[i] != '\0'; ++i);
    for(j = 0; s2[j] != '\0'; ++j, ++i){
        s1[i] = s2[j];
    }
    s1[i] = '\0';
    return s1;
}

int main(){

    char file_name[100];
    for(int k=0; k<10; k++){
        // Get data
        // ...
        // Create filename
        strcpy(file_name, get_file_name(k));
        printf("%s", file_name);
        // fp = fopen(file_name, "w+");
        // Write data to file
        // print_results_to_file();
        // fclose(fp);
    }

    return 0;
}

此刻,我收到以下我不理解的错误:

    string.c: In function ‘get_file_name’:
string.c:14:12: warning: returning ‘char *’ from a function with return type ‘char’ makes integer from pointer without a cast [-Wint-conversion]
     return s1;
            ^~
string.c:14:12: warning: function returns address of local variable [-Wreturn-local-addr]
string.c: In function ‘main’:
string.c:24:27: warning: passing argument 2 of ‘strcpy’ makes pointer from integer without a cast [-Wint-conversion]
         strcpy(file_name, get_file_name(k));
                           ^~~~~~~~~~~~~~~~
In file included from string.c:2:
/usr/include/string.h:121:14: note: expected ‘const char * restrict’ but argument is of type ‘char’
 extern char *strcpy (char *__restrict __dest, const char *__restrict __src)
              ^~~~~~

是否有更简单的方法来创建此类文件名?我不敢相信没有。

4 个答案:

答案 0 :(得分:2)

函数get_file_name的返回类型为char

char get_file_name(int k){

但它返回类型为char *

的对象
char s1[100] = "logs/data_";
//...
return s1;

此外,返回的指针指向本地数组s1,该数组在退出函数后将不活动。

在此次通话中

strcpy(file_name, get_file_name(k));

第二个自变量的类型(根据函数char的定义为get_file_name)应为char *

既没有函数print_results_to_file的声明,也没有其定义。

根据C标准,没有参数的main函数应声明为

int main( void )

我将以以下方式编写函数get_file_name

#include <stdio.h>
#include <string.h>

char * get_file_name( char *file_name, size_t n, size_t padding )
{
    const char *common_part = "logs/data_";

    snprintf( file_name, n, "%s%zu", common_part, padding );

    return file_name;
}    

int main( void )
{
    enum { N = 100 };
    char file_name[N];

    for ( size_t i = 0; i < 10; i++ ) puts( get_file_name( file_name, N, i ) );
}

程序输出为

logs/data_0
logs/data_1
logs/data_2
logs/data_3
logs/data_4
logs/data_5
logs/data_6
logs/data_7
logs/data_8
logs/data_9

答案 1 :(得分:2)

此代码存在各种问题,而不是一个一个地纠正一个问题。它不仅是唯一的,而且很简单,应该易于理解和适应:

#include <stdio.h>

void get_file_name(int k, char* buffer, size_t buflen) {
    snprintf(buffer, buflen, "logs/data_%d.log", k);
}

int main() {
    const size_t BUFLEN = 50;
    char file_name[BUFLEN];

    for (int i = 0; i < 10; i++) {
        get_file_name(i, file_name, BUFLEN);
        printf("%s\n", file_name);
        // Code for writing to file.
    }
}

一些细节:

  1. 此函数不尝试返回(指向)内存,而是传递写入的缓冲区。调用者必须确保缓冲区足够大(在这里总是如此,但是如果实际文件名较长,则应添加逻辑来检查snprintf的返回值并执行适当的错误处理)

  2. 该函数的实际逻辑只需要对snprintf的一个调用,该调用已经执行了您需要的所有操作,因此尚不清楚是否需要单独的函数甚至是有用的。

    < / li>
  3. 上面使用可变长度数组。如果要确保恒定的缓冲区,可以使用#define代替const size_t变量作为缓冲区长度。但是,在这里使用可变长度数组很好,有些编译器甚至将其转换为常量数组。

如评论中所述,重要的是,您(a)阅读并了解所使用功能的文档,以及(b)阅读并了解编译器错误消息。

答案 2 :(得分:0)

您的代码有几个问题,但是最大的问题是您试图从get_file_name返回指向局部变量的指针。

这很重要,因为char s1[100]之后立即释放了get_file_name中为return分配的内存。

其余错误是因为您忘记了*中的char get_file_name(int k)

有几种可能的解决方案:

  1. 传入char数组以填充函数。
  2. 使用全局变量(这是一种不好的做法)。
  3. 动态分配内存。
  4. 将局部变量设为静态(这有点棘手,但合法)

答案 3 :(得分:0)

您的错误很容易解释:

get_file_name应该返回一个char,但是您创建一个char[]并返回它(它与char*相同)

get_file_name返回在函数本身中创建的数组的地址。函数结束后,该数组可能会被覆盖。将数组添加为参数或使用malloc

strcpy不起作用,因为它期望char*char[])而不是charget_file_name返回char

print_results_to_file未定义。您可能需要包含程序中使用的其他文件(例如,如果功能在文件func.c中实现,则原型应位于通过func.h包含的名为#include "func.h"的文件中。