I have to write a function in c which will return a dynamic array of strings. Here are my requirements:
I have 10 different examine functions which will return either true or false and associated error text. (error text string is also dynamic).
My function must collect the result(true or false) + the error string and it will be called n examine functions. So my function must collect n results and finally return a dynamic array of strings to other functions.
You can allocate an array of arbitrary length with malloc() (it's like "new" in Java), and make it grow or shrink with realloc().
You have to remember to free the memory with free() as in C there is not garbarage collector.
Check: http://www.gnu.org/software/libc/manual/html_node/Memory-Allocation.html#Memory-Allocation
Edit:
#include <stdlib.h>
#include <string.h>
int main(){
char * string;
// Lets say we have a initial string of 8 chars
string = malloc(sizeof(char) * 9); // Nine because we need 8 chars plus one \0 to terminate the string
strcpy(string, "12345678");
// Now we need to expand the string to 10 chars (plus one for \0)
string = realloc(string, sizeof(char) * 11);
// you can check if string is different of NULL...
// Now we append some chars
strcat(string, "90");
// ...
// at some point you need to free the memory if you don't want a memory leak
free(string);
// ...
return 0;
}
Edit 2:
This is the sample for allocate and expand an array of pointers to chars (an array of strings)
#include <stdlib.h>
int main(){
// Array of strings
char ** messages;
char * pointer_to_string_0 = "Hello";
char * pointer_to_string_1 = "World";
unsigned size = 0;
// Initial size one
messages = malloc(sizeof(char *)); // Note I allocate space for 1 pointer to char
size = 1;
// ...
messages[0] = pointer_to_string_0;
// We expand to contain 2 strings (2 pointers really)
size++;
messages = realloc(messages, sizeof(char *) * size);
messages[1] = pointer_to_string_1;
// ...
free(messages);
// ...
return 0;
}
Consider creating apropriate types suitable for you problem. For example, you can create a struct holding a pointer and sn integer length to represent the dynamic arrays.
Do you have some constraints over
the prototyping of the examine()
function and the function you have
to write ? (let's call it
validate())
You say you have 10 examine() functions, does it mean you will have a maximum of 10 messages/results in the array return by validate() ?
I'm a Java programmer with a C background, so maybe I can highlight a few things for you :
there is no equivalent of Array.length in C : you'll have to supply a side integer value to store the effective size of your array
C arrays can't "grow" : you'll have to use pointers and allocate/reallocate the memory pointed by your array begin pointer as this array grows or shrinks
you should already know that there is no notion of class or method in C, however you can use struct, typedef and function pointers to add some kind of object oriented / genericity behavior to your C programs...
Depending on your needs and obligations, arrays might be a good way to go, or not : perhaps you should try to figure out a way of building/finding an equivalent of the java List interface in C, so that you can add, remove/destroy or sort examine result elements without having to duplicate memory allocation / reallocation / freeing code each time you manipulate your result set (and you should perhaps send a header file with your structs/examine functions to describe what you did for now anyway, and express your needs a bit more precisely, so that we can guide you to the good direction)
Don't hesitate to provide more information or ask for specifics about the above bullets points ;)
Related
I have an array of strings with a given size, without using any memory allocation, how do I append something into it?
Say I run the code, its waiting for something you want to enter, you enter "bond", how do I append this into an array ? A[10] ?
If the array declared like
char A[10];
then you can assign string "bond" to it the following way
#include <string.h>
//...
strcpy( A, "bond" );
If you want to append the array with some other string then you can write
#include <string.h>
//...
strcpy( A, "bond" );
strcat( A, " john" );
You can't append to an array. When you define the array variable, C asks the is for enough contiguous memory. That's all the memory you ever get. You can modify the elements of the array (A[10]=5) but not the size.
However, you CAN create data structures that allow appending. The two most common are linked lists and dynamic arrays. Note, these are no built into the language. You have to implement them yourself or use a library. The lists and arrays of Python, Ruby and JavaScript are implemented as dynamic arrays.
LearnCThHardWay has a pretty good tutorial on linked lists, though the one on dynamic arrays is a little rough.
Hi,
It really depends on what you mean by append.
...
int tab[5]; // Your tab, with given size
// Fill the tab, however suits you.
// You then realize at some point you needed more room in the array
tab[6] = 5; // You CAN'T do that, obviously. Memory is not allocated.
The problem here can be two things :
Did you misjudge the size you need ? In that case, just make sure this given size you mentioned is correctly 'given', however that might be.
Or don't you know how much room you want at the beginning ? In that case, you''ll have to allocate the memory yourself ! There is no other way you can resize a memory chunk on the fly, if I might say.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define STR_MAX_SIZE 255 // Maximum size for a string. Completely arbitray.
char *new_string(char *str)
{
char *ret; // The future new string;
ret = (char *) malloc(sizeof(char) * 255); // Allocate the string
strcpy(ret, str); // Function from the C string.h standard library
return (ret);
}
int main()
{
char *strings[STR_MAX_SIZE]; // Your array
char in[255]; // The current buffer
int i = 0, j = 0; // iterators
while (in[0] != 'q')
{
printf("Hi ! Enter smth :\n");
scanf("%s", in);
strings[i] = new_string(in); // Creation of the new string, with call to malloc
i++;
}
for ( ; j < i ; j++)
{
printf("Tab[ %d ] :\t%s\n", j, strings[j]); // Display
free(strings[j]); // Memory released. Important, your program
// should free every bit it malloc's before exiting
}
return (0);
}
This is the easiest solution I could think of. It's probably not the best, but I just wanted to show you the whole process. I could have used the C standard library strdup(char *str) function to create a new string, and could have implemented my own quick list or array.
The size of an array variable cannot change. The only way to append to an array is to use memory allocation. You are looking for the realloc() function.
If you want to append a character or string to it;
strcpy(a, "james")
strcpy(a, "bond")
I basically want to store a array of student names, based on a given number. For example, if the user wants to insert 5 names, then the array size will be 5. If the user wants to insert 10 names, then the array size will be 10.
I have a method like this to set a name to a specific element in an array.
void setNames(char *names){
strcpy(name[i], names);
}
Thing is, how do I do array bound checks? I heard that you can only add when the index is -1.
Arrays don't maintain their own size, you have to do that for them. This is part of the reason why vectors are so much easier to deal with, and why everyone will say "wtf, raw arrays? use a vector". An array is just a contiguous chunk of memory, thats it. a vector contains an array, and lets you use it like an array to some extent, but it handles a lot of the housekeeping details for you.
Anyway, if you really want to use a raw array, then you'll need to pass around size information along with it. C strings are a null-terminated array -- just a plain old array, but the last element is \0. This way you can read from it without knowing it's size ahead of time, just don't read past the null character at the end (dragons be there).
EDIT (as the OP indicated he actually wants C):
C answer
What you can do is either create a char array:
char [N][name_length]
where N - number "user wants" (I assume the user will somehow input it into your program), name_length - maximum length the name can have (a C-string, i.e. null-terminated string).
or create an array of your own structs (each holding a separate name and maybe some other information).
C++ answer
A typical way to do this in C++ is by using std::vector<std::string> (assuming you only want to store names, as std::string).
You then add new elements using using push_back() function. And, as vector is implemented as a dynamic array in C++, you won't have to do bound checking.
C code needs to keep track of the array size in another variable.
typedef struct {
char **name;
size_t n;
} Names_T;
void Names_Set(Names_T *names, size_t index, const char *name) {
// See if it is a special value and then append to the array
if (index == (size_t) -1) {
index = names->n;
}
if (index >= names->n) {
size_t newsize = index + 1;
// OOM error handling omitted
names->name = realloc(names->name, newsize * sizeof *names->name);
while (names->n < newsize) {
names->name[names->n++] = NULL;
}
}
char *oldname = names->name[index];
names->name[index] = strdup(name);
free(oldname);
}
void Names_Delete(Names_T *names) {
while (names->n > 0) {
names->n--;
free(&names->name[names->n]);
names->name[names->n] = NULL;
}
free(names->name);
names->name = NULL;
}
int main(void) {
Names_T names = { NULL, 0 };
Names_Set(&names, 3, "Sam"); // set array element 3
Names_Set(&names, (size_t) -1, "Thers"); // Append to array
Names_Delete(&names);
return 0;
}
When programming in C/C++ (unless using C++11 or newer), you will manipulate arrays as pointers. That means you won't know the size of an array unless you save it. What char str[10] really means is str's address + 10 * sizeof(char). You are directly dealing with memory here.
If you want a high level approach for that, take a look at C++11. std::array and std::vector are there for you. From the documentation, look how std::array is defined:
template <
class T,
std::size_t N
> struct array;
It means it stores its own size and has useful functions as well, such as size(), at(), back() etc.
Let's consider following piece of code:
int len = 100;
char *buf = (char*)malloc(sizeof(char)*len);
printf("Appended: %s\n",struct_to_string(some_struct,buf,len));
Someone allocated amount of memory in order to get it filled with string data. The problem is that string data taken from some_struct could be ANY length. So what i want to achieve is to make struct_to_string function do the following:
Do not allocate any memory that goes outside (so, buf has to be allocated outside of the function, and passed)
Inside the struct_to_string I want to do something like:
char* struct_to_string(const struct type* some_struct, char* buf, int len) {
//it will be more like pseudo code to show the idea :)
char var1_name[] = "int l1";
buf += var1_name + " = " + some_struct->l1;
//when l1 is a int or some non char, I need to cast it
char var2_name[] = "bool t1";
buf += var2_name + " = " + some_struct->t1;
// buf+= (I mean appending function) should check if there is a place in a buf,
//if there is not it should fill buf with
//as many characters as possible (without writting to memory) and stop
//etc.
return buf;
}
Output should be like:
Appended: int l1 = 10 bool t1 = 20 //if there was good amount of memory allocated or
ex: Appended: int l1 = 10 bo //if there was not enough memory allocated
To sum up:
I need a function (or couple of functions) that adds given strings to the base string without overwritting base string;
do nothing when base string memory is full
I can not use C++ libraries
Another things that I could ask but are not so important right now:
Is there a way (in C) iterate through structure variable list to get their names, or at least to get their values without their names? (for example iterate through structure like through array ;d)
I do not normally use C, but for now I'm obligated to do, so I have very basic knowledge.
(sorry for my English)
Edit:
Good way to solve that problem is shown in post below: stackoverflow.com/a/2674354/2630520
I'd say all you need is the standard strncat function defined in the string.h header.
About the 'iterate through structure variable list' part, I'm not exactly sure what you mean. If your talking about iterating over the structure's members, a short answer would be : you can't introspect C structs for free.
You need to know beforehand what structure type you're using so that the compiler know at what offset in the memory it can find each member of your struct. Otherwise it's just an array of bytes like any other.
Don't mind asking if I wasn't clear enough or if you want more details.
Good luck.
So basically I did it like here: stackoverflow.com/a/2674354/2630520
int struct_to_string(const struct struct_type* struct_var, char* buf, const int len)
{
unsigned int length = 0;
unsigned int i;
length += snprintf(buf+length, len-length, "v0[%d]", struct_var->v0);
length += other_struct_to_string(struct_var->sub, buf+length, len-length);
length += snprintf(buf+length, len-length, "v2[%d]", struct_var->v2);
length += snprintf(buf+length, len-length, "v3[%d]", struct_var->v3);
....
return length;
}
snprintf writes as much as possible and discards everything left, so it was exactly what I was looking for.
Since I'm very new to C programming, I have a probably very simple problem.
I got a struct looking like this
typedef struct Vector{
int a;
int b;
int c;
}Vector;
Now I want to write an array of Vectors in a file. To achieve that, I thought to create following method scheme
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;
}
My main problems are at (1), which involves also (2) (since I have no clue how to work with Strings in C, eclipse is saying "Type "String" unknown", although I included <string.h>)
So I read at some point that transforming an int to a String is possible with the method itoa().
As I understood it, I can simply do following
char buf[33];
int a = 5;
itoa(a, buf, 10)
However, I cannot bring that to work, let alone that I can't figure out how to "paste" chars or ints into a String.
In my point (1), I would like to create a String of the Form (a,b,c), where as a, b and c are the "fields" of my struct Vector.
In point (2), I would like to create a single String of the Form (a1,b1,c1)\n(a2,b2,c2)\n...(an,bn,cn), whereby n is the amount of Vectors in the array.
Is there a quick solution? Do I confuse the concept of Strings from Java with them of C?
Yes, you do confuse the concept of strings in Java and C.
The C strings are rather inconvenient to work with. They require dynamic memory allocation, and what is worse, corresponding deallocation (which is possible but tedious). In your case, it might be best to remove strings completely, and implement whatever you need without strings.
To write a vector directly to file:
Vector vec;
FILE* file = ...;
fprintf(file, "%d %d %\n", vec.a, vec.b, vec.c);
To write an array of vectors, just do the above in a loop.
A string, in C, is just a null-terminated array of characters. It is generally declared as a char *, though if you have a fixed maximum length, and can allocate it on the stack or inline in a structure, it might be declared as char str[LENGTH].
One of the easiest ways to build a string out of a mix of characters and numbers is to use snprintf(). This is like printf(), but instead of printing to standard output, will print into a string (an array of char). Note that you need to allocate and pass in the buffer yourself; so you will either need to know the maximum length beforehand, or find out by trying to call snprintf(), finding out how many characters it would print, allocating an array of that size, and calling snprintf() again to actually print the result.
So if you have a vector of three integers, and want to build a string out of it, you could write:
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;
}
Note that because you called malloc() to allocate this buffer, you will need to call free() once you are done with it, to avoid a memory leak.
Note that snprintf() only returns the length that you need as of C99. Some compilers (like MSVC), don't support C99 yet, so they return -1 instead of the length that the string would be. In those cases, there may be another function that you can call to determine the size of buffer you need (in MSVC, it's _vscprintf), or you may need to just guess at a size, and if that doesn't work, allocate a buffer twice that size and try again, until it succeeds.
In short: yes, you are confusing Java Strings with C, where you do not have standard string type. What is a string is in reality a sequence of chars terminated with a char with value 0 (or '\0', if you want to be purist).
The quickest solution is to not generate strings (and manually allocate all the memory), but rather to use fprintf with FILE*. Instead of functions to create strings, write functions to write various things into supplied FILE*, for example int writeVector(FILE* output, Vector v). It will be easier for the beginning. I don't think all the gory details of manual memory management required for constructing such strings are good start.
(Note the return type of int in proposed prototype; this is for error codes.)
Additionally, as one of the commenters noted, you misunderstand sizeof. sizeof(arr) would return size of all the elements of the array combined, in bytes (well, technically in chars, but it's a distinction you don't need to worry about right now). To get number of elements in an array, you'd need to use sizeof(arr)/sizeof(arr[0]). But I'm not sure it would work with your function argument, which is technically a pointer, despite the fancy syntax. Applying sizeof to pointer will return size of the pointer itself, not the data it points to.
Which is why in C you would usually provide size of an array in an extra function argument, like:
String createVectorArrayString(Vector arr[], size_t n)
or more in line with what I wrote above:
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;
}
}
Yes, you are confusing Java Strings with C.
you can't pass arrays in C, only pointers to the first element.
sizeof (arr) where arr is a function argument is the size of the pointer.
You can't return a block scope String, only a pointer to a string. But pointers to local automatic variables go out of scope when the function returns.
I'd write a loop more along
#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);
}
I'm trying to write more efficient code in a C program, and I need some help getting my pointers and assignments correct. I've shown two methods below, each using the following declarations and strncpy:
int kk, arraysize;
char person_name[100] = "";
char * array_person_name, * array_param;
...
strncpy(person_name, "John Smith", 100);
arraysize = <this value is downloaded from database>;
...
Method A (rectangular array):
array_person_name = malloc( sizeof(char) * arraysize *100 );
array_param = malloc( sizeof(char) * arraysize * 2 );
for (kk = 0; kk < arraysize; kk++) {
strncpy(array_person_name[kk], person_name, 100);
strncpy(array_param[kk], "bt", 2);
}
Method B (ragged array):
for (kk = 0; kk < arraysize; kk++) {
array_person_name[kk] = &person_name;
array_param[kk] = "bt";
}
Notice that the arrays I'm trying to create place the same value into each element of the array. Method A is an (rectangular) array of arraysize elements, each element itself being an array of 100 characters. Method B attempts not to waste storage space by creating an (ragged) array of arraysize elements, where each element is a pointer-to-char.
QUESTION 1: Am I allocating memory (e.g. malloc) correctly in Method A?
QUESTION 2: Does the syntax look correct for Method B?
QUESTION 3: How do I allocate memory for the arrays in method B?
QUESTION 4: Am I correct that Method B is generally preferred?
You are pretty far off here. 1:yes, 2:no, 3:no, 4:yes. I'm not going to do it all, but here are a few hints.
You need space to store the strings and space to store pointers to the strings (the latter isn't strictly necessary for Method A). The first will have type char*, the second will have type char**.
For Method A, you are allocating the string storage correctly, but you need to allocate the storage for the string pointers correctly (hint: you need arraysize instances of a char* pointer). It then gets initialized to pointers which differ from each other by 100 characters.
For Method B, there is no easy way of allocating space to store the strings, as you don't know how much space you'll need. You could iterate through all the strings once just to count their length, or do one malloc per string, or use a fixed size chunk and allocate more when you run out.
Method B uses the same string storage pointer array as Method A. You need to assign the string pointers into the array once you know where they will go.