由于我对C编程很陌生,我可能有一个非常简单的问题。
我有一个看起来像这样的结构
typedef struct Vector{
int a;
int b;
int c;
}Vector;
现在我想在文件中写一个Vectors数组。为此,我想创建以下方法方案
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说“类型”字符串“未知”,虽然我包括{{1} })
所以我在某种程度上读到了使用itoa()方法将int转换为String的可能性。 据我了解,我可以简单地按照
进行操作<string.h>
但是,我无法将其付诸实践,更不用说我无法弄清楚如何将char buf[33];
int a = 5;
itoa(a, buf, 10)
或char
“粘贴”到字符串中。
在我的观点(1)中,我想创建一个Form int
的字符串,其中a,b和c是我的struct Vector的“字段”。
在(2)中,我想创建一个Form (a,b,c)
的字符串,其中n是数组中Vector的数量。
有快速解决方案吗?我是否将Java中的字符串概念与C语言混淆了?
答案 0 :(得分:4)
是的,你确实混淆了Java和C中字符串的概念。
C字符串使用起来相当不方便。它们需要动态内存分配,更糟糕的是,相应的重新分配(这是可能的但是单调乏味)。在您的情况下,最好完全删除字符串,并在没有字符串的情况下实现您需要的任何内容。
将矢量直接写入文件:
Vector vec;
FILE* file = ...;
fprintf(file, "%d %d %\n", vec.a, vec.b, vec.c);
要编写一个向量数组,只需在循环中执行上述操作。
答案 1 :(得分: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
),或者您可能需要猜测一个大小,如果不是工作,分配两倍大小的缓冲区并重试,直到成功。
答案 2 :(得分:1)
简而言之:是的,你将Java Strings与C混淆,你没有标准的字符串类型。什么是字符串实际上是一个字符序列,以一个值为0的字符结束(如果你想要纯粹,则为'\ 0')。
最快的解决方案是不生成字符串(并手动分配所有内存),而是将fprintf
与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;
}
}
答案 3 :(得分:1)
是的,你 混淆Java字符串与C。
sizeof (arr)
其中arr是函数参数,是指针的大小。我会更多地写一个循环
#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);
}