0

由于我对 C 编程非常陌生,因此我可能遇到了一个非常简单的问题。

我有一个看起来像这样的结构

typedef struct Vector{
    int a;
    int b;
    int c;
}Vector;

现在我想在一个文件中写入一个向量数组。为此,我想创建以下方法方案

String createVectorString(Vector vec){
    // (1)
}

String createVectorArrayString(Vector arr[]){
    int i;
    String arrayString;
    for(i=0; i<sizeof(arr); i++){
        //append createVectorString(arr[i]) to arrayString  (2)
    }
}

void writeInFile(Vector arr[]){
    FILE *file;
    file = fopen("sorted_vectors.txt", "a+");
    fprintf(file, "%s", createVectorArrayString(arr);
    fclose(file);
}

int main(void){

    // create here my array of Vectors (this has already been made and is not part of the question)
    // then call writeInFile

    return 0;
}

我的主要问题在于 (1),其中还涉及 (2)(因为我不知道如何在 C 中使用字符串,所以 eclipse 说“类型“字符串”未知”,尽管我包括在内<string.h>

所以我在某些时候读到,使用 itoa() 方法可以将 int 转换为 String。据我了解,我可以简单地执行以下操作

char buf[33];
int a = 5;
itoa(a, buf, 10)

但是,我无法将其用于工作,更不用说我无法弄清楚如何将chars 或ints “粘贴”到字符串中。

在我的观点(1)中,我想创建一个 String 的 Form (a,b,c),其中 a、b 和 c 是我的 struct Vector 的“字段”。

在第(2)点,我想创建一个 String 的 Form (a1,b1,c1)\n(a2,b2,c2)\n...(an,bn,cn),其中 n 是数组中向量的数量。

有没有快速的解决方案?我是否将 Java 中的字符串概念与 C 中的字符串概念混淆了?

4

4 回答 4

4

是的,您确实混淆了 Java 和 C 中字符串的概念。

C 字符串使用起来相当不方便。它们需要动态内存分配,更糟糕的是,需要相应的释放(这是可能的,但很乏味)。在您的情况下,最好完全删除字符串,并在没有字符串的情况下实现您需要的任何内容。

要将向量直接写入文件:

Vector vec;
FILE* file = ...;
fprintf(file, "%d %d %\n", vec.a, vec.b, vec.c);

要编写向量数组,只需在循环中执行上述操作。

于 2012-10-18T20:02:26.740 回答
2

在 C 中,字符串只是一个以空字符结尾的字符数组。它通常被声明为char *,但如果你有一个固定的最大长度,并且可以将它分配到堆栈上或在结构中内联,它可能被声明为char str[LENGTH]

使用混合字符和数字构建字符串的最简单方法之一是使用snprintf(). 这就像printf(),但不是打印到标准输出,而是打印到一个字符串(一个数组char)。注意需要自己分配和传入缓冲区;所以你要么需要事先知道最大长度,要么通过尝试调用来snprintf()找出它,找出它将打印多少个字符,分配一个该大小的数组,然后snprintf()再次调用以实际打印结果。

因此,如果您有一个由三个整数组成的向量,并且想从中构建一个字符串,您可以编写:

char *createVectorString(Vector vec){
    int count = snprintf(NULL, 0, "(%d,%d,%d)", vec.a, vec.b, vec.c);
    if (count < 0)
        return NULL;
    char *result = malloc(count * sizeof(char));
    if (result == NULL)
        return NULL;
    count = snprintf(result, count, "(%d,%d,%d)", vec.a, vec.b, vec.c);
    if (count < 0)
        return NULL;
    return result;
}

请注意,由于您调用malloc()来分配此缓冲区,因此您需要在free()完成后调用它,以避免内存泄漏。

请注意,snprintf()仅返回 C99 起您需要的长度。一些编译器(如 MSVC)还不支持 C99,因此它们返回 -1 而不是字符串的长度。在这些情况下,您可以调用另一个函数来确定所需缓冲区的大小(在 MSVC 中,它是_vscprintf),或者您可能只需要猜测一个大小,如果这不起作用,请分配一个缓冲区两倍大小,然后再试一次,直到成功。

于 2012-10-18T20:14:47.757 回答
1

是的,您Java 字符串与 C 混淆了。

  1. 您不能在 C 中传递数组,只能传递指向第一个元素的指针。
  2. sizeof (arr)其中 arr 是函数参数是指针的大小。
  3. 您不能返回块范围字符串,只能返回指向字符串的指针。但是当函数返回时,指向本地自动变量的指针超出范围。

我会写一个循环更多

#define N 42

/* Typedef for Vector assumed somewhere.*/
Vector arr[N];
/* Fill arr[]. */

for (i = 0; i < N; ++i) {
    fprintf (file, "arr[%d] =  { a=%d, b=%d, c=%d }\n", i, arr[i].a, arr[i].b, arr[i].c);
}
于 2012-10-18T20:06:16.640 回答
1

简而言之:是的,您将 Java 字符串与 C 混淆了,因为您没有标准的字符串类型。什么是字符串实际上是一系列以值为 0 的 char 结尾的字符(或 '\0',如果你想成为纯粹主义者)。

最快的解决方案是不生成字符串(并手动分配所有内存),而是使用fprintfwith FILE*. 代替创建字符串的函数,编写将各种内容写入提供的函数FILE*,例如int writeVector(FILE* output, Vector v). 开始会更容易。我不认为构建此类字符串所需的手动内存管理的所有血腥细节都是好的开始。

(注意建议原型中 int 的返回类型;这是用于错误代码的。)

此外,正如其中一位评论者指出的那样,您误解了 sizeof。sizeof(arr)将返回数组中所有元素组合的大小,以字节为单位(嗯,从技术上讲,以字符为单位,但这是你现在不需要担心的区别)。要获取数组中的元素数量,您需要使用sizeof(arr)/sizeof(arr[0]). 但是我不确定它是否可以与您的函数参数一起使用,尽管语法很花哨,但从技术上讲,它是一个指针。将 sizeof 应用于指针将返回指针本身的大小,而不是它指向的数据。

这就是为什么在 C 语言中,您通常会在额外的函数参数中提供数组的大小,例如:

String createVectorArrayString(Vector arr[], size_t n)

或者更符合我上面写的:

int writeVectorArray(FILE *output, Vector arr[], size_t n)
{
  int retcode = 0;
  size_t i;
  for (i = 0; i < n; ++i) {
    if ( (retcode = writeVector(output, arr[i])) != 0)
      return retcode;
  }
}
于 2012-10-18T20:04:26.770 回答