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.
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]);
}
In C, If I have:
char *reg = "[R5]";
and I want
char *reg_alt = "R5" (equal to the same thing, but without the brackets), how do I do this?
I tried
*char reg_alt = reg[1:2];
but this doesn't work.
There is no built-in syntax for dealing with substrings like that, so you need to copy the content manually:
char res[3];
memcpy(res, ®[1], 2);
res[2] = '\0';
I suggest you need to read a basic text on C, rather than assuming techniques from other languages will just work.
First, char *reg = "[R5]"; is not a string. It is a pointer, that is initialised to point to (i.e. its value is the address of) the first character of a string literal ("[R5]").
Second, reg_alt is also a pointer, not a string. Assigning to it will contain an address of something. Strings are not first class citizens in C, so the assignment operator doesn't work with them.
Third, 1:2 does not specify a range - it is actually more invalid syntax. Yes, I know other languages do. But not C. Hence my comment that you cannot assume C will allow things it the way that other languages do.
If you want to obtain a substring from another string, there are various ways. For example;
char substring[3];
const char *reg = "[R5]"; /* const since the string literal should not be modified */
strncpy(substring, ®[1], 2); /* copy 2 characters, starting at reg[1], to substring */
substring[2] = '\0'; /* terminate substring */
printf("%s\n", substring);
strncpy() is declared in standard header <string.h>. The termination of the substring is needed, since printf() %s format looks for a zero character to mark the end.
When using null-terminated strings (the default in C), you can indeed cheaply create a substring of another string by simply changing the starting character pointer, but you cannot make the new substring have a different null-terminator.
An option is to use a Pascal-string library. Pascal-strings are length-prefixed instead of C-strings which are null-terminated, which means Pascal-strings can share contents of a larger string buffer and substring generation is cheap (O(1)-cheap). A Pascal string looks like this:
struct PString {
size_t length;
char* start;
}
PString substring(const PString* source, size_t offset, size_t length) {
// Using C99 Designated Initializer syntax:
return PString { .length = length, .start = source.start + offset };
}
The downside is that most of the C library and platform libraries use null-terminated strings and unless your Pascal-string ends in a null character you'll need to copy the substring to a new buffer (in O(n) time).
Of course, if you're feeling dangerous (and using mutable character buffers) then you can hack it to temporarily insert a null-terminator, like so:
struct CStr {
char* start;
char* end;
char temp;
}
CStr getCStr(PString* source) {
char* terminator = (source.start + source.length);
char previous = *terminator;
*terminator = '\0';
return CStr { .start = source.start, .end = terminator, .temp = previous };
}
void undoGetCStr(CStr cstr) {
*cstr.end = cstr.temp;
}
Used like so:
PString somePascalString = doSomethingWithPascalStrings();
CStr temp = getCStr( somePascalString );
printf("My Pascal string: %s", temp.start ); // using a function that expects a C-string
undoGetCStr( temp );
...which then gives you O(1) PString-to-CString performance, provided you don't care about thread-safety.
Need to be a char?
Because that only work when is a "string"
So maybe you need this
char reg[] = "[R5]";
Then you can do the other thing
or just split the string like this question
Apologies if my following question sounds trivial but I'm struggling with the fundamental concept of "converting an a char array to a string" for use in the method strstr().
Essentially I have an array called EUI_only[] which is dynamically populated at a certain stage of my program i.e.
EUI_only[0] = A;
EUI_only[1] = B;
EUI_only[2] = C;
EUI_only[3] = D;
EUI_only[4] = E;
I declared EUI_only as follows at the top of my program:
char EUI_only[];
I can confirm that EUI_only[] is successfully populated as justbefore I use it in method strstr() I print it out.
Now I have the second array called receive_key_press_temporary_analysis_buffer which I intend on utilising in my strstr() i.e. the array which contains characters similar to those in EUI_only.
This array is also dynamically populated in a certain point of my program and I can confirm that the contents of the array are intact just before I use it in strstr() as I've printed this array.
Content of this array called receive_key_press_temporary_analysis_buffer can be seen below:
receive_key_press_temporary_analysis_buffer[0] = 1;
receive_key_press_temporary_analysis_buffer[1] = 2;
receive_key_press_temporary_analysis_buffer[2] = C;
receive_key_press_temporary_analysis_buffer[3] = A;
receive_key_press_temporary_analysis_buffer[4] = B;
receive_key_press_temporary_analysis_buffer[5] = C;
receive_key_press_temporary_analysis_buffer[6] = D;
receive_key_press_temporary_analysis_buffer[7] = E;
receive_key_press_temporary_analysis_buffer[8] = 3;
receive_key_press_temporary_analysis_buffer[9] = 4;
Below essentially is how I use both arrays in strstr():
char* is_eui_only_content_in_receive_key_press_analysis = strstr(receive_key_press_temporary_analysis_buffer, EUI_only);
printf("\n\rResult of is_eui_only_content_in_receive_key_press_analysis: %s\n\r", is_eui_only_content_in_receive_key_press_analysis);
Basically when I print the outcome of strstr() it gives me:
Result of is_eui_only_content_in_receive_key_press_analysis: CDE34
On the other hand if I reinitialise my EUI_only follows:
EUI_only[] = "ABCDE";
Essentially I get the expected result from the strstr() i.e.
Result of is_eui_only_content_in_receive_key_press_analysis: ABCDE34
Why could it be the strstr() doesn't give me my expected result when I utilise my dynamically populated EUI_only[] array?
Thanks,
Alex.
If your only definition is char EUI_only[]; then it actually has a size of 1. You cause a buffer overflow by writing 5 characters to it. In C, arrays don't automatically resize; they have a fixed size for their lifetime.
Successfully printing its contents doesn't prove anything, as it could perhaps happen that you write into memory you don't own, but nothing disturbs that memory in between the write and the read.
Secondly, the str functions expect a string. The definition of a string is a series of characters followed by a null character. In your example code you do not have the null character, so even if you did not have the allocation problem, you don't actually have a string; therefore the function misbehaves.
When you write char EUI_only[] = "ABCDE"; , it is doing char EUI_only[6] = { 'A', 'B', 'C', 'D', 'E', 0 }; which is a string, so everything works as expected.
Update: The reason the array size would be 1 is covered by C99 6.9.2, "tentative definitions". After the line char EUI_only[];, EUI_only has incomplete type. For an incomplete array type, you can dereference it, but you can't do sizeof on it. You may complete the type at any point later on in the source file; and if you don't, then it behaves as if the last line of the source file was char EUI_only[] = { 0 };. This is a rarely-used feature of C; usually you would declare a complete type by either specifying the size, or providing an initializer.
C strings are terminated by null '\0' character
EUI_only[5] = '\0' ;
and
receive_key_press_temporary_analysis_buffer[10] = '\0' ;
Make sure you have extra space for null character at declaration.
Newbie to programming (school) and I'm a little confused on what/why this is happening.
I have a loop that is iterating over an array of elements, for each element I am taking the integer of the array, converting it to a char using the function getelementsymbol, and using strcat to append to my temp array. The problem I am having is that the elements of my temp array contain the residual of the element proceeding it. This is the snippet of my code. The output I receive is this:
word1
word1word2
word1word2word3
char* elementsBuildWord(const int symbols[], int nbSymbols){
/* ROLE takes a list of elements' atomic numbers and allocate a new string made
of the symbols of each of these elements
PARAMETERS symbols an array of nbSymbols int which each represent the atomic number
of an element
nbSymbols symbols array's size
RETURN VALUE NULL if the array is of size <= 0
or if one of the symbols is not found by our getElementSymbol function
other the address of a newly allocated string representing the concatenation
of the names of all symbols
*/
char s1[MAX_GENERATED_WORD_LENGTH];
int y;
char *s2;
size_t i;
for (i = 0; i < nbSymbols; i++){
y = symbols[i];
s2 = getElementSymbol(y);
strcat(s1, s2);
}
printf("%s ", s1);
}
Firstly, your s1 is not initialized. strcat function append a new string to an existing string. This means that your s1 has to be a string from the very beginning. An uninitialized char array is not a string. A good idea would be to declare your s1 as
char s1[MAX_GENERATED_WORD_LENGTH] = { 0 };
or at least do
s1[0] = '\0';
before starting your cycle.
Secondly, your getElementSymbol function returns a char * pointer. Where does that pointer point to? Who manages the memory it points to? This is non-obvious from your code. It is possible that the function returns an invalid pointer (like a pointer to a local buffer), which is why might see various anomalies. There's no way to say without seeing how it is implemented.
strcat is supposed to append to a string. use strcpy if you want to overwrite the existing string. You could also use s1[0] = '\0'; before strcat to "blank" the string if you really want to, but looks like you really want strcpy.
From the snippet above it's not even clear why you need s1 - you could just print s2...
I am trying to copy certain parts of a string into other, new strings, but when i try to do it and print the results it gives me weird output.. I really hope someone can help. I have a feeling that it is something about missing pointers.. Here is my source;
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void getData(char code[], char ware[], char prod[], char qual[])
{
printf("Bar code: %s\n", code);
/* Copy warehouse name from barcode */
strncpy(ware, &code[0], 3);
ware[4] = "\0";
strncpy(prod, &code[3], 4);
prod[5] = "\0";
strncpy(qual, &code[7], 3);
qual[4] = "\0";
}
int main(){
/* allocate and initialize strings */
char barcode[] = "ATL1203S14";
char warehouse[4];
char product[5];
char qualifier[4];
getData(&barcode, &warehouse, &product, &qualifier);
/* print it */
printf("Warehouse: %s\nID: %s\nQualifier: %s", warehouse, product, qualifier);
return 0;
}
EDIT:
The wierd output is:
Bar code: ATL1203S14
Warehouse: ATL
ID: ♫203(♫>
Qualifier: S14u♫203(♫>
I think you meant '\0' instead of "\0" and 3 instead of 4:
ware[4] = "\0";
Try:
ware[3] = 0;
Also the & in getData(&barcode, &warehouse...) are useless. Just use getData(barcode, warehouse...);.
You're writing past the end of the chars in your getData() function. You've defined char product[5], which allocates 5 bytes of memory. That gives you array indexes 0,1,2,3,4. In getData, you write the product's null terminator to index 5, which is past the end of product, and will overwrite the next var's first character.
The same applies for barecode, warehouse, and qualifier.
Arrays in C and C++ are zero-based. The last index is one less than the length. You're setting a value in the memory after the array, for each of the arrays ware, prod and qual.
For example, instead of
char warehouse[4];
ware[4] = "\0";
you'd want:
char warehouse[4];
ware[3] = "\0";
getData(&barcode, &warehouse, &product, &qualifier);
This is not the way you should call getData. getData takes pointers, arrays are automatically converted to pointers, so theres no need to use the address-of operator &.
You should use
getData(barcode, warehouse, product, qualifier);
The sizes of the strings inside main() don't include a place for the sentinel.
You need to have:
char warehouse[5];
char product[6];
char qualifier[5];
Also, You are assigning a pointer to the string "\0" into a character, where you should be assigning the character '\0' itself.
I think I'd do things a bit differently. In particular, strncpy is almost never really useful (I'm reasonably certain it was invented for file names in the original Unix FS, and while it fits their specific requirements quite nicely, those requirements are sufficiently unusual that it's rarely good for much of anything else).
Instead, I'd use sscanf: sscanf(code, "%4c%5c%4c", ware, prod, qual);
Your question does not make it clear whether this is really correct. As others have pointed out, you're writing past the ends of the space you've allocated. Above, I've assumed you specified the number of characters you want to copy, so you'd have to expand each of the allocations by one character to make room for the terminator. Alternative, if you've already left room for the terminator and want one fewer character copied, you'd have to reduce each of the lengths above by one so the format string would be "%3c%4c%3c".