C program giving weird output - c

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".

Related

Using a char* or a char array for strings within a struct

If I have the following pseudocode for a struct I would like to implement in C (for a text editor):
STRUCT line
STRING line_contents
INT line_length
END
Is there a best practice for how I write my strings? I see two options:
struct line {
char* line_contents;
size_t line_length;
};
or...
#define MAX_LINE_LENGTH 1024 // Some arbitrary number
struct line {
char line_contents[MAX_LINE_LENGTH];
size_t line_length;
};
The first one has the drawback of leaving the programmer with manual memory management, however, this is likely to be the case anyway with structs if they're part of a linked list/some other advanced data structure.
The second one might use too much or too little memory, it opens itself up to out of bounds errors, etc.
Is the way you deal with strings dependent on your use case or is there a universal best practice?
There is no generic best practice on this one. It is mainly wasted space vs. complexity of the code.
As a rule of thumb, you might consider the typical line lengths you have in your typical documents - In a text editor, 1 vs. maybe 100 bytes, so a maximum "waste" of 99 bytes per line, which, in my opinion is acceptable on modern, non-memory-restricted machines. The point is: Once your user wants a line of 101 characters, you're forced to either tell your users about the limit, or introduce expensive work-arounds for the case of extra long lines (and, revert back to complexity).
You might, however, want to consider that line-oriented editor buffers have been widely out of fashion since at least 30 years. The most-used (and accepted, IMHO) buffer architecture is the one Emacs introduced like 30 years ago - A big chunk of memory with an insertion gap that is moved back and forth to the place the user is editing.
Is the way you deal with strings dependent on your use case or is there a universal best practice?
There is no "universial best" pratice. It always depend on your your specific use case.
But... your use case is a text editor so using a struct with a fixed maximum line length just seems wrong to me.
But I like to show a third way which uses a flexible array member:
struct line {
size_t line_length;
char line_contents[]; <--- Flexible array.
malloc determines the size
};
int main()
{
char* str = "Hello World";
size_t len = strlen(str);
struct line* l = malloc(sizeof *l + len + 1);
\-----/
sizeof the array
l->line_length = len;
strcpy(l->line_contents, str);
printf("Len %zu: %s\n", l->line_length, l->line_contents);
free(l);
return 0;
}
In this way a single malloc can allocate both a new node and memory for the string.
The solution that is being commonly used in C libraries is by using the internal string.h library.
Strings in C are being designed with a null terminator in the end that basically says where the string ends. The null terminator is a '\0' character. The C string scheme is shown here.
Your code can be reformatted to the following bellow.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const int MAX_STRING_LENGTH = 256;
int main()
{
/*+1 for the additional null terminator*/
char* line = malloc(MAX_STRING_LENGTH + 1);
strcpy(line, "Hello stack overflow!");
/*'line' can hold up to 256 byte long strings, but to get the
length of "Hello stack overflow!" string that was transfered
into 'line' variable, you can use 'strlen()' function as shown
below.*/
printf("Length of 'line' string: %d\n", strlen(line));
return 0;
}

How to return a string to main function?

I am trying to write code to implement strchr function in c. But, I'm not able to return the string.
I have seen discussions on how to return string but I'm not getting desired output
const char* stchr(const char *,char);
int main()
{
char *string[50],*p;
char ch;
printf("Enter a sentence\n");
gets(string);
printf("Enter the character from which sentence should be printed\n");
scanf("%c",&ch);
p=stchr(string,ch);
printf("\nThe sentence from %c is %s",ch,p);
}
const char* stchr(const char *string,char ch)
{
int i=0,count=0;
while(string[i]!='\0'&&count==0)
{
if(string[i++]==ch)
count++;
}
if(count!=0)
{
char *temp[50];
int size=(strlen(string)-i+1);
strncpy(temp,string+i-1,size);
temp[strlen(temp)+1]='\0';
printf("%s",temp);
return (char*)temp;
}
else
return 0;
}
I should get the output similar to strchr function but output is as follows
Enter a sentence
i love cooking
Enter the character from which sentence should be printed
l
The sentence from l is (null)
There are basically only two real errors in your code, plus one line that, IMHO, should certainly be changed. Here are the errors, with the solutions:
(1) As noted in the comments, the line:
char *string[50],*p;
is declaring string as an array of 50 character pointers, whereas you just want an array of 50 characters. Use this, instead:
char string[50], *p;
(2) There are two problems with the line:
char *temp[50];
First, as noted in (1), your are declaring an array of character pointers, not an array of characters. Second, as this is a locally-defined ('automatic') variable, it will be deleted when the function exits, so your p variable in main will point to some memory that has been deleted. To fix this, you can declare the (local) variable as static, which means it will remain fixed in memory (but see the added footnote on the use of static variables):
static char temp[50];
Lastly, again as mentioned in the comments, you should not be using the gets function, as this is now obsolete (although some compilers still support it). Instead, you should use the fgets function, and use stdin as the 'source file':
fgets(string, 49, stdin);/// gets() has been removed! Here, 2nd argument is max length.
Another minor issue is your use of the strlen and strncpy functions. The former actually returns a value of type size_t (always an unsigned integral type) not int (always signed); the latter uses such a size_t type as its final argument. So, you should have this line, instead of what you currently have:
size_t size = (strlen(string) - i + 1);
Feel free to ask for further clarification and/or explanation.
EDIT: Potential Problem when using the static Solution
As noted in the comments by Basya, the use of static data can cause issues that can be hard to track down when developing programs that have multiple threads: if two different threads try to access the data at the same time, you will get (at best) a "data race" and, more likely, difficult-to-trace unexpected behaviour. A better way, in such circumstances, is to dynamically allocate memory for the variable from the "heap," using the standard malloc function (defined in <stdlib.h> - be sure to #include this header):
char* temp = malloc(50);
If you use this approach, be sure to release the memory when you're done with it, using the free() function. In your example, this would be at the end of main:
free(p);

how to load a char[] that's a member of Stuct[i]?

Let's say we have this struct
struct Foo{
int FooLength; //length of Foo
char FooChar[4];
};
and then in the main we have
int sizeFoo = 100; struct Foo myFooList[sizeFoo];
what would be the best way to input data for FooChar? Would strncpy, or memcpy, or snprintf, or sprintf?
what I wish to do is something like
myFooList[0].FooLength = 3;
myFooList[0].FooChar = "dog";
myFooList[1].FooLength = 3;
myFooList[1].FooChar = "cat";
.
.
.
with a correct syntax since in C you can't just = "string"; here, and I'm not sure what would be the best way to go about it? I have look at similar topics, but I just get more confused with how strncpy or sprintf are not good or you have to have a \0 added at the end or some other detail that makes picking what to do more difficult.
Also if all the values of myFooList[] are already know (they are const or static) is there a way to initialize like one would do any other array?
If your input is always 3 characters, you can use strcpy, otherwise use strncpy(myFooList[0].FooChar, "dog", 3). You must add the terminating null character if using strncpy. strcpy will add the termination null character automatically, just like VHS has in his answer. In either case, you should still validate that your input does not exceed the maximum length. To find the length of a string(i.e. the number of char characters up to the first null character), you would use strlen. To determine the capacity of a char a[], you can use _countof(a). Don't forget that one of those has to be a '\0'.
memcpy would also work, but it would be unusual to do that with a string.
You wouldn't use sprintf here. sprintf would normally be used when you need to create a unique string using dynamic data at runtime. This is not what you're doing here. If you have any experience with .NET, it is the C equivalent of string.Format.
To initialize an array of 'Foo', you will just need to write a function that will do that. Even if you figure out the syntax to do it in one line, it'll be very difficult to read and maintain. Here's an example without validation, I will leave that task to you.
myFooList[0].FooLength = 3;
strncpy(myFooList[0].FooChar, "dog", 3);
myFooList[0].FooChar[3] = '\0';
myFooList[1].FooLength = 3;
strncpy(myFooList[1].FooChar, "cat", 3);
myFooList[1].FooChar[3] = '\0';
Your integer assignment is correct, but the string assignment is not. Following is the right way:
myFooList[0].FooLength = 3;
strcpy( myFooList[0].FooChar, "dog");
myFooList[1].FooLength = 3;
strcpy(myFooList[1].FooChar, "cat");
what would be the best way to input data for FooChar? Would strncpy,
or memcpy, or snprintf, or sprintf? ...
but I just get more confused with how strncpy or sprintf are not good
or you have to have a \0 added at the end or some other detail that
makes picking what to do more difficult.
Well, memcpy is a good choice if you don't want terminate nul byte. I don't really understand what is your question here.
Also if all the values of myFooList[] are already know (they are const
or static) is there a way to initialize like one would do any other
array?
In your example, no, because you use VLA who can't be initialize. But you could do the following:
#include <stdio.h>
struct Foo {
int FooLength; // length of Foo
char FooChar[4];
};
int main(void) {
struct Foo myFooList[] = {{3, "dog"}, {3, "cat"}};
size_t size = sizeof myFooList / sizeof *myFooList;
}

Receive an array of strings from a function and find out it's length [closed]

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]);
}

Char x[50] and Char x[100] Output

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.

Resources