This question already has answers here:
How can I correctly assign a new string value?
(4 answers)
Closed 1 year ago.
#include<stdio.h>
int main() {
char R_FPD[] = "+00393E33mm/go";
char R_FPH[] = "+00393E33mm/go";
char R_Vel[] = "+00393E33mm/go";
char R_Tot[] = "+00393E33mm/go";
char str_msg[] = "{"+"flow_rate_per_day"+":"+R_FPD+","+"flow_rate_per_hour"+":"+R_FPH+","+"velocity"+":"+R_Vel+","+"totalizer"+":"+R_Tot+"}";
printf("%s", str_msg);
return 0;
}
i want to make it like a json object but its not working
Arrays in C decay to pointers to their first elements and adding pointers is not defined in C standard.
The simplest way to concatenate string like this is using sprintf function. It works like printf but it prints into a C-string.
In your case the pattern could be following:
char str_msg[BIG_ENOUGH];
sprintf(str_msg, "{flow_rate_per_day:%s,flow_rate_per_hour:%s,velocity:%s,totalizer:%s}", R_FPD,R_FPH,R_Vel,R_Tot);
BIG_ENOUGH should be larger then the longest string that can be formed. 256 should be enough in your case.
Alternatively you can use asprintf function that will automatically allocated a buffer of the right size. Remember to use free when the buffer is no longer needed.
char *str_msg;
asprintf(&str_msg, "{flow_rate_per_day:%s,flow_rate_per_hour:%s,velocity:%s,totalizer:%s}", R_FPD,R_FPH,R_Vel,R_Tot);
... use str_msg
free(str_msg);
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I have this code:
char** SplitToWords(char* str);
int main()
{
char** wordarr;
char str[] = "This is a sentence";
wordarr = SplitToWords(str);
return 0;
}
After the main comes the function implementation.
I am not sure the following does what I want it to do (i.e. receive an array of strings from a function):
wordarr = SplitToWords(str);
I somehow managed to convince the compiler that it's ok, but I assume it just does something else.
If it does, how do I find out the length of the array (the number of strings in it).
Thanks
I'll try to quickly visit all aspects you might not yet fully understand:
A string in C is described as a contiguous sequence of chars, ending with a char of value 0 (as a literal: '\0'). It is not a first class object, therefore hasn't its own type. So what you use to hold a string is an array of char. Therefore, taking your question by the word, "receive an array of strings from a function" is not possible.
An array is a contiguous sequence of objects of the same type. In C, the identifier of an array doesn't have a value itself; when it's evaluated, it decays as a pointer to the array's first element instead. This is especially important when passing arrays to functions or returning them from functions -- you can't actually pass the array, you always pass a pointer
e.g. you could write:
char x[] = "foo"; // initialize a char array from a string literal
char *xp = x; // here, x evaluates as a pointer to the first element of the array
You already use pointer types for your function's argument and return value, I just think it's quite important to understand what happens entirely.
You write char** SplitToWords(char* str); and ask whether this returns an "array of strings" -- well, sort of, as you should understand after reading 1. and 2. -- What it does is returning a pointer to char *. This pointer could be a pointer to the first element of an array. So in this case, it would return a pointer to an array of char * pointers. Each of these pointers could itself be a pointer to an array of chars, therefore point to a string. But what's very important is to understand you never return an array, you always return a pointer to it. It's so important because:
You might get the idea to do something like this:
char** SplitToWords(char* str)
{
char *words[16];
// code to fill `words` with pointers to the actual words
return words; // WRONG!
}
Here, because you're not returning the array words but a pointer to it (see point 2), you return a pointer to an object that no longer exists. words is in the scope of your function and has automatic storage duration, that means it only lives as long as the execution is inside of the function. One solution would be to declare words with the static storage class specifier. This way, it lives for the entire execution time of the program. But be aware that this also means there's only a single instance ever, it's always the same object. This will be a major headache for threaded programs, for example. The other way around is to dynamically allocate words using malloc(). But then, the caller of the function must free() it later.
As for your second question, how to let the caller know the number of words -- it's in the comments already, but just for completeness, a typical approach to solve this is to append another entry that is a NULL pointer. So the caller can iterate over the pointers until it finds NULL.
Regarding your comment, of course you can create the array outside the function and pass a pointer to the function, so the function only fills it. This is a common idiom in C (e.g. think about fgets(), which takes a pointer to the char array that's filled with a string by the function).
Functions working this way will need an additional size_t parameter, so they know the size of the array they should fill through the pointer, otherwise you'd have the risk of buffer overflows (this is why gets() was finally removed from the C standard). If you decide that the caller provides the storage, your function should have this prototype:
// returns the number of words found, up to `nwords`
size_t SplitToTwords(char **words, size_t nwords, char *str);
It should be called e.g. like this:
char *words[16];
size_t nwords = SplitToWords(words, 16, "the quick brown fox"); // returns 4
Remember that the strings holding the words themselves need storage as well. You can either manipulate the bytes in str to insert a '\0' after each word, overwriting the first whitespace character (this is what strtok() does) or you can copy the words to new strings, but then you would have to malloc() each of them again and the caller has to free() them later.
Yes, you could solve it by using a function with return value char **. However, there's no way to find out how many words there are afterwards.
You can solve this by allocating one more element for the return pointer and set it to NULL. Then you can get the number of words with this code:
wordarr = SplitToWords(str);
char **ptr=wordarr;
int noWords=0;
while(!*(ptr+noWords))
noWords++;
But if you want to return multiple data in C, you either need to define a return struct or using return arguments. In this case, it could look like this for the first option:
typedef struct wordList {
char **wordarr;
int noWords;
}
wordList SplitToWords(char* str);
And the second:
char** SplitToWords(char* str, int *noWords);
or
void SplitToWords(char* str, char*** wordarr, int *noWords);
Note that there's three *. That's because we want it to be a pointer to char **
#include "stdafx.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXSTRINGS 5000
int main(int argc, char *argv[]) {
char *stringTable[MAXSTRINGS];
char sentence[] = "This is a sentence";
char *token = NULL;
int i = 0;
while ((token = strtok(token == NULL ? sentence : NULL, " ")) != NULL)
{
printf("%s\n\r", token);
stringTable[i] = (char *)malloc(strlen(token) + 1); //have no "plain" C compiler - VS C++ used so cast needed :)
strcpy(stringTable[i++], token);
}
stringTable[i] = NULL; // if you need to iterate through later
printf("%d tokens found\n\r", i);
for (int y = 0; y < i; y++)
free(stringTable[y]);
}
This question already has answers here:
Crash or "segmentation fault" when data is copied/scanned/read to an uninitialized pointer
(5 answers)
Closed 6 years ago.
I'm trying out the following code:
int main()
{
char *yo = "yo";
char *whaddup = NULL;
strcpy(whaddup,yo);
}
and I get a segfault. Complete C noob here - other places say I should initialize whaddup as an array. Why can't I pass in a pointer to null?
Just any strcpy documentation will tell you that the destination string should be a char array large enough to hold the string and the NUL terminator.
So what you need is something like
char* yo = "yo";
char* whaddup = malloc(strlen(yo)+1);
strcpy(whaddup, yo);
Or alternatively you could use strdup function which does this for you, but it's not standard as it's POSIX only.
You have to either declare whaddup as a character array or ideally allocate space for it with malloc.
int main()
{
char *yo = "yo";
char *whaddup = malloc(sizeof(char) * 8); // buffer for 8 characters
strcpy(whaddup,yo);
}
By initializing whaddup to NULL you are not giving it any space in memory, so even copying one character into it will result in a segmentation fault.
You can pass in a pointer to null, but you can not copy string from pointer to null.
The function char* strcpy(char* dest, const char* src) is copy string from address src to address dest, your dest is null.
This question already has answers here:
returning a local variable from function in C [duplicate]
(4 answers)
Closed 7 years ago.
I am quite new to C and I am playing with some string operations. I have encountered quite a strange problem for me while returning a string from a function. My simple program is as follows:
int main(int argc, char* argv[])
{
char text[] = "abAB";
char* out = testString(text);
printf("Result Text: %s", out);
printf("\n");
}
char* testString(char* input) {
char* text = copyString(input);
return text;
}
The copyString function defines a simple operation to copy one string to another. It is as follows:
char* copyString(char* input) {
char output[100];
int index = 0;
while (input[index] != '\0') {
output[index] = input[index];
index++;
}
output[index] = '\0';
return output;
}
The problem is that while I am debugging the application, the string I am returning from a function seems to be OK (Visual Studio visualises it well enough) and when the printf line occurs, the string outputted on the stdout is something completely strange and unfamiliar - a smily face. Sadly, I can't post images yet in order to show you what I see in my console as output.
I am using Visual C++ Express 2010 as an IDE if this could be helpful.
You are returning a variable declared within a function, which will cease to exist outside the scope in which it is declared. Use a dynamically allocated char array and then return a pointer to it.
char* output = malloc(100 * sizeof(char));
...
return output ;
Note : You are assuming that input string is less than 100 characters. Instead of that, try passing the length of string as a parameter or use strlen. Your program will crash if input string has more than 99 characters.
Also as noted in comments, free the memory allocated when you are done using it.
This question already has answers here:
How do I concatenate const/literal strings in C?
(17 answers)
Closed 9 years ago.
I realize the following will not work but is there an equivalent?
const char *foo = "foo";
static char *end = sprintf ("%s_bar", foo);
What I want to do is concatenate strings and then make that concatenated string a static variable so that it becomes a global variable. Also I like not having to assign memory to a char. I need this to go in main() because I need to use a function (sprintf) to merge two strings.
Superficially, you could revise the code as follows:
#define FOO_INITIALIZER "foo"
const char *foo = FOO_INITIALIZER;
static char *end = FOO_INITIALIZER "_bar";
I'm not sure how much it buys you, but it should compile and avoids repetition of the strings. It uses adjacent string literal concatenation, which is standard in C89 and later (but not in pre-standard compilers).
I think you can do it with the stringizing operator.
#define STR_CONCAT(x, y) #x#y
static char *end = STR_CONCAT(foo, _bar);
int main(void)
{
printf("%s", end); // prints out "foo_bar"
getchar();
return 0;
}
sprintf is declared as int sprintf(char *str, const char format, ...); char* str is the buffer to which the output will be written, however malicious users might put more to that buffer than the sizeof that buffer therefore one can also use snprintf which includes a parameter that contains the size of the output buffer so bufferoverflows will not happen. What you should note it returns the number of bytes written, therefore you cannot assign it to a char or char[].
const char* foo = "foo";
static char end[BUFSIZE];
snprintf(end, BUFSIZE, ""%s_bar", foo);
I prefer to use snprintf for it doesn't as easily result in a buffer overflow which is a security error. Now it can atmost print BUFSIZ characters to end you can look if the concatenation succeeded if snprintf returns strlen("s_bar") + strlen("foo");
What you can also do is:
char end[BUFSIZE] = "foo_";
strncat( end, "_bar", BUFSIZ);
which is perhaps more what you like.
I'm not used to C as I'm primarily a Java guy, with some knowledge of C++, so forgive me if this is a trivial question. I could not seem to find an answer while searching online.
I'm initializing a char array...
char tcp[50];
So that I can concatenate a const char and a char. In examples I saw an easy way to do this was by creating that empty char array and then using...
strcat(x,y);
To stick them together.
Problem is, printing out the blank char array when it is set to "50" gives me a result of:
X??|?
When I change it to...
char tcp[100];
And print it, its blank. Why is this?
The array contents are undefined, assuming it is a local (automatic) array.
Use:
char tcp[50] = "";
Or:
char tcp[50] = {0};
Or:
char tcp[50];
tcp[0] = 0;
Or:
char tcp[50];
memset(tcp, 0, sizeof(tcp));
As you like.
Always null terminate you char arrays before doing anything:
tcp[0] = '\0';
C happily allocates the space for the array you declare, but it does not set its content to 0.
Therefore, the content of the array you're printing is random (or rather depending in the previous contents of the memory)
When creating an array, the compiler puts it somewhere in memory but does not initialize it, so whatever is in that memory when the program is started will be the initial "string".
Terminate the string manually after you created the array, either by making the whole array "zeroed" out, or just put zero as the first character:
char tcp[50] = { '\0' };
Or
char tcp[50];
/* ... */
tcp[0] = '\0';
The difference here is, you're essentially working with two empty arrays trying to merge them in the memory space of one (not sure if that makes sense for you).
First of all, in C you have to terminate strings with \0. That's something not exposed or visible in Java. Also you essentially used two undefined strings (as there's no value set).
#include <stdio.h>
#include <string.h>
char target[256];
const char source_a[] = "Hello";
const char source_b[] = "World!";
int void(main)
{
target[0] = '\0'; // this essentially empties the string as we set the first entry to be the end. Depending on your language version of C, you might as well write "char target[256] = {'\0'};" above.
strcat(target, source_a); // append the first string/char array
strcat(target, " "); // append a const string literal
strcat(target, source_b); // append the second string
printf("%s\n", target);
return 0;
}
Important: Using strcat() can be unsave, as there's no length check performed, and other than Java, these "strings" have a fixed length (the one you set when defining the variables). If there's no length given, but you copy a string on initialization, that length is taken (e.g. char test[] = "Hello!"; will be 7 chars long (due to terminating \0)).
If you'd like a more Java like approach on strings, use C++ and the std::string class, that performs a lot more similar to Java's strings.