Change string value from another function in main in C using pointers - c

I have this code, and I want from a string that is stored in value called original such as home$family$fun, using the delimiter value such as $, assign to another string named final the word between the two delimiters. That means that final should contain family and print the result from main. But the operation must be done in another function using only pointer and pointer arithmetic. Also the prototype of the getPart function must not be changed.
My problem is that, I get this result to my variable final when I am inside the getPart function but when I am returning to main the final function have only '\0' as value and not the value I wanted it. I think, the problem is something with the addresses, meaning that if the value which string's address change, then the value of string will be changed. But I am a bit confused...Could someone help me?
#include <stdio.h>
#include <string.h>
#define SIZE 32
int getPart(char original[], char delimiter[], char final[]) {
int i, j;
int counter = 0;
int counter1 = 0;
for(i = 0; *(original + i) != '\0'; i++) {
if(*(original + i) == *delimiter) {
counter++;
}
}
if(counter > 1) {
for(i = 0; *(original + i) != '\0'; i++) {
if(*(original + i) == *delimiter) {
if(counter1 < 1) {
final = (original + i + 1);
counter1++;
}
else {
for(j = 0; *(final + j) != '\0'; j++) {
if(strcmp(final + j,original + i) == 0) {
*(final + j) = '\0';
*(final + j + 1) = '\0';
//final + j = '\0';
}
}
}
}
}
return(1);
}
else {
return(0);
}
}
int main(int argc, char *argv[]) {
char original[SIZE], delimiter[SIZE], final[SIZE];
char format_str_or[20], format_str_del[20];
int counter, i;
for(i = 0; i < SIZE; i++) {
*(final + i) = '\0';
}
sprintf(format_str_or," %%%ds",SIZE - 1);
printf("Enter string: ");
scanf(format_str_or,original);
sprintf(format_str_del," %%%ds", SIZE - 1);
printf("Enter delimiter: ");
scanf(format_str_del,delimiter);
counter = getPart(original,delimiter,final);
printf("%d\n",counter);
if(counter == 1) {
printf("%s\n",final);
}
else if(counter == 0) {
printf("%s does not appear twice in %s\n",delimiter,original);
}
return(0);
}

Two problems:
In your function you reassign the pointer final to point somewhere into original. Reassignment won't work as the pointer is passed by value, and the assignment only changes the local variable.
By modifying contents of final you also modify the contents of original.
Both these issues could be solved by copying to final instead of reassigning where it points.
Both these issues should also be easily detectable using standard debugging practices.

Related

How to go through a array of strings using pointers alone

I'm trying to create a function that will receive an array of strings and the size and will return a string made of the biggest ASCII value's letter of each word, and the size of the string has to be precised and I'm not allowed using operator [](which is my main issue).
so for:
char *strArr[SIZE] = { "hello", "and", "good", "morning" };
the function shall return a string with the word
"onor"
.
So i thought of creating a double for loop, first one will lead me into the location of each word in the array and the inside one will help me go through each word.
currently I'm having trouble finding the right format with my pointers to actually go through the letters of my first word.
I'm aware i haven't checked if my memory allocation is valid and also didn't free my memory yet as I'm trying to figure out whats wrong first.
char *bigLetters(char *str[], int size)
{
char *strNew = (char *)malloc((size + 1) * sizeof(char));
char max = 'a';
for (int i = 0; i < size; i++)
{
for (int j = 0; (*(str + i)+j) != NULL; j++)
{
if ((*(str + i) + j) >= max)
{
max = (*(str + i) + j);
}
}
*(strNew + i) = max;
}
*(strNew +(size+1)) = NULL;
return *(strNew);
}
void main()
{
char *strArr[SIZE] = { "hello", "and", "good", "morning" };
char *res = bigLetters(strArr, SIZE);
printf("The new string is --> %s\n", res);
system("pause");
}
It will be easier to use the pointers if you separate the string pointer from its character pointer. Also, the max needs to be reset for each string, and you were writing the final string terminator outside of the memory allocated. You also use NULL where you should be using the character '\0'.
Finally the function was returning the first character of the new string (which I later free).
#include <stdio.h>
#include <stdlib.h>
#define SIZE 4
char *bigLetters(char *str[], int size)
{
char *strNew = malloc(size + 1); // no cast or sizeof necessary
for (int i = 0; i < size; i++)
{
char ch;
char max = 'a'; // moved inside loop
char *ptr = *(str + i); // use a separate pointer
for (int j = 0; (ch = *(ptr + j)) != '\0'; j++) // pull out the character
{
if (ch > max) // >= is not necessary
{
max = ch;
}
}
*(strNew + i) = max;
}
*(strNew + size) = '\0'; // correct the bounds error
return strNew; // just the pointer not its target
}
int main(void) // correct signature
{
char *strArr[SIZE] = { "hello", "and", "good", "morning" };
char *res = bigLetters(strArr, SIZE);
printf("The new string is --> %s\n", res);
free(res); // clean up
system("pause");
}
Program output
The new string is --> onor
Press any key to continue . . .
If you didn't impose odd and unhelpful restrictions upon your coding, you'd be able to quickly see the problems with your code or even avoid making them in the first place. The problem is that the following statement makes no sense - you're comparing a char * with a char as you're only de-referencing str once.
if ((*(str + i) + j) >= max)
This is the same as writing
if ((str[i] + j) >= max)
which you can see the obvious mistake since what you're trying to write is the equivalent of
if ((str[i][j]) >= max)
which would be
if (*(*(str + i) + j) >= max)
Your compiler should be throwing up warnings because comparing between a pointer and an integer is rarely something you'd want to do.
You can use pointers as position indicators and advance them as needed.
#include <stdio.h>
#include <stdlib.h>
#define SIZE 4
char
biggest_ascii(char* str)
{
char c = 0;
int i;
for (i = 0; *str; str++)
if (*str > c)
c = *str;
return c;
}
int
main()
{
int i;
char* strArr[SIZE] = {"hello", "and", "good", "morning"};
char** ppch;// current string
char res_str[SIZE + 1] = {0};/* resulting string,
initilized to 0 to be 0-terminated */
char* pch;// current char position
for (i = 0, ppch = strArr, pch = res_str; i < SIZE; i++, ppch++, pch++)
*pch = biggest_ascii(*ppch);
printf("%s\n", res_str);
return 0;
}
First, (*(str + i)+j) isn't the good way.
You could replace all
(*(str + i) + j)
by :
str[i][j]
Then, you need to reset the max to "a", because it's 'o' when you leave the loop, so your condition become str[i][j] >= o which is not what you want. Do it before the second for.
And I would have used while instead of for for the first loop.
I edited your code and this version is working fine for me :
#include <stdlib.h>
char *bigLetters(char *str[], int size)
{
char *strNew = (char *)malloc((size + 1) * sizeof(char));
int i = 0;
while (i < size) {
char max = 'a';
for (int j = 0; str[i][j]; j++) {
if (str[i][j] >= max) {
max = str[i][j];
}
}
strNew[i] = max;
i++;
}
strNew[i] = '\0';
return strNew;
}
void main()
{
char *strArr[5] = { "hello", "and", "good", "morning"};
char *res = bigLetters(strArr, 4);
printf("The new string is --> %s\n", res);
return 0;
}
str[i] is equivalent to *(str + i) and str[i][j] is equivalent to *(*(str + i) + j).
In your code you are using (*(str + i) + j) which is incorrect.
When char *[] passed to function, it will decay to char **. So, in bigLetters(), you can give char **str as the parameter. Also, it is inline with you requirement - not allowed using operator [].
Instead of hardcoding the dimension SIZE in char *strArr[SIZE], you can give the empty [] and let the compiler assign the dimension based on the size of initializer. In your case, size of initializer is 4 as you have given 4 strings in the strArr initializer. You can compute the size of strArr like this:
sizeof(strArr)/sizeof(strArr[0]);
You can do:
#include <stdio.h>
#include <stdlib.h>
char *bigLetters(char **str, size_t size) {
char *strNew = calloc(size + 1, 1); // sizeof(char) is always 1
// calloc will initialize all bytes in the allocated storage to zero.
// You dont need to add the null terminating character at the end of strNew
if (strNew == NULL)
exit(EXIT_FAILURE);
for (size_t i = 0; i < size; i++) {
for (size_t j = 0; *(*(str + i)+j) != '\0'; j++) {
if (*(*(str + i) + j) > *(strNew + i)) {
// You can directly fill the allocated memory with biggest ASCII
*(strNew + i) = *(*(str + i) + j);
}
}
}
return strNew;
}
int main(void) {
char *strArr[] = { "hello", "and", "good", "morning" };
char *res = bigLetters(strArr, sizeof(strArr)/sizeof(strArr[0]));
if (res != NULL) {
printf("The new string is --> %s\n", res);
free (res);
}
else
printf("bigLetters returned NULL\n");
return 0;
}
Note that void return type main() is not as per standard. Instead, you should use int as return type of main().

How can I change an array of string pointers in another function?

I have been trying to figure out how to modify an array of char pointers but no matter what I do there appears to be no change below are the three arrays I'm trying to change including the call to the function I'm using.
char*cm1[5];
char*cm2[5];
char*cm3[5];
setupCommands(&cm1,commands,file,0);
setupCommands(&cm2,commands,file,1);
setupCommands(&cm3,commands,file,2);
The code below is the function itself.I was thinking that maybe it involves a double pointer but if I try *cmd to change the array I get a segmentation fault.
void setupCommands(char **cmd[], char* commands[],char file[],int index){
char str1[255];
strcpy(str1,commands[index]);
char newString [5][255];
int j = 0;
int ctr = 0;
int i;
//printf("str1 %s\n" ,str1);
for(i = 0; i <= strlen(str1); i++){
if(str1[i] == ' '|| str1[i] =='\0'){
newString[ctr][j] = '\0';
ctr++;//next row
j=0;// for next word, init index to 0
}else{
newString[ctr][j]=str1[i];
j++;
}
}
for(i = 0; i < ctr; i++){
//printf(" test2 %s \n", newString[i]);
cmd[i] = newString[i];
//printf(" test2 %d %s \n", i,cmd[i]);
}
//printf("index %d", i);
cmd[i]= file;
cmd[i + 1] = NULL;
//execvp(cmd[0],cmd);
//cmd
}
There are a few issues with your code:
you are trying to return references to the local 'char newString [5][255]' when the function exits. In simple worlds - never return anything locally allocated on the stack. This is the reason you are getting the segmentation fault.
char **cmd[] must be declared char *cmd[] - even though you will get a warning from the compiler assignment from incompatible pointer type, the code would run and execute correctly(essentially **cmd[] would do the same work as *cmd[], even though it's not of correct type) if you didn't return references to the local object;
Easy and simple optimization is just to remove the array str1 and directly operate on the array commands.
Apart from this simple optimization I have changed your code to overcome the segmentation fault, by allocating on the heap, instead on stack(will live until the program terminates) the multidimensional array, and I also calculate it's size so I will know how much memory to allocate. Now it's safe to return references to it.
Note that more optimizations could be made, but for the sake of the simplicity this is the bare minimal for this code to work.
int setupCommands(char *cmd[], char *commands[], char file[], int index)
{
int j = 0;
int ctr = 0;
int i = 0;
int rows = 0;
int cols = 0;
char **newString = NULL;
while(commands[index][i])
{
if (commands[index][i] == ' ')
{
++rows;
}
++i;
}
++rows;
cols = strlen(commands[index]) + 1;
newString = malloc(rows * sizeof(*newString));
if (newString == NULL)
{
return -1;
}
for (i = 0; i < rows; ++i)
{
newString[i] = malloc(cols * sizeof(*newString));
if (newString[i] == NULL)
{
return -1;
}
}
for(i = 0; i <= strlen(commands[index]); i++){
if(commands[index][i] == ' '|| commands[index][i] =='\0'){
newString[ctr][j] = '\0';
ctr++;//next row
j=0;// for next word, init index to 0
}else{
newString[ctr][j]=commands[index][i];
j++;
}
}
for(i = 0; i < ctr; i++){
cmd[i] = newString[i];
}
cmd[i]= file;
cmd[i + 1] = NULL;
return 0;
}
First of all - being the three stars pointer programmer is not good :)
You assign it with pointer to the local variable which is not longer available after the function return
But if you still want the three stars pointers:
char **cm1;
char **cm2;
char **cm3;
setupCommands(&cm1,commands,file,0);
setupCommands(&cm2,commands,file,1);
setupCommands(&cm3,commands,file,2);
#define MAXWORD 256
int setupCommands(char ***cmd, const char *commands,const char *file,int index){
char str1[255];
strcpy(str1,commands[index]);
int j = 0;
int ctr = 0;
int i;
//printf("str1 %s\n" ,str1);
*cmd = malloc(sizeof(char *));
**cmd = malloc(MAXWORD);
if(!*cmd || !**cmd)
{
/* do spmething if mallocs failed*/
return -1;
}
for(i = 0; i <= strlen(str1); i++){
if(str1[i] == ' '|| str1[i] =='\0'){
(*cmd)[ctr][j] = '\0';
ctr++;//next row
*cmd = realloc((ctr + 1) * sizeof(int));
(*cmd)[ctr] = malloc(MAXWORD);
if(!*cmd || !*cmd[ctr])
{
/* do spmething if mallocs failed*/
return -1;
}
j=0;// for next word, init index to 0
}else{
(*cmd)[ctr][j]=str1[i];
j++;
}
}
*cmd = realloc(sizeof(char *) * ctr + 2)
(*cmd)[ctr - 2] = malloc(MAX);
if(!*cmd || !*cmd[ctr - 2])
{
/* do spmething if mallocs failed*/
return -1;
}
strcpy((*cmd)[ctr - 2], file);
(*cmd)[ctr - 1] = NULL;
return 0;
//execvp(cmd[0],cmd);
//cmd
}
you can improve many things (for example do not realloc every time but in the larger chunks) and I did not change anything in your code logic.

returning string in C function [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 6 years ago.
Improve this question
I was trying to solve CountAndSay problem at one of the online coding site but I am not able to get why my program is printing NULL. I am sure I am doing some conceptual mistake but not getting it.
Here is my code :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* countAndSay(int A) {
int i,j,k,f,count;
char a;
char *c = (char*)malloc(sizeof(char)*100);
char *temp = (char*)malloc(sizeof(char)*100);
c[0] = 1;c[1] = '\0';
for(k=2; k<=A; k++)
{
for(i=0, j=0; i<strlen(c); i++)
{
a = c[i];
count = 1;
i++;
while(c[i] != '\0')
{
if(c[i]==a)
{
count++;
i++;
}
else if(c[i] != a)
{
i--;
break;
}
else
{
break;
}
}
temp[j] = count;
temp[j+1] = a;
j += 2;
}
*(temp+j) = '\0';
if(k<A)
{
for(j=0; j<strlen(temp); j++)
{
c[j] = temp[j];
}
c[j] = '\0';
}
}
return temp;
}
int main(void) {
// your code goes here
char *c = countAndSay(8);
printf("%s\n",c);
return 0;
}
The idea is not that bad, the main errors are the mix-up of numerical digits and characters as shown in the comments.
Also: if you use dynamic memory, than use dynamic memory. If you only want to use a fixed small amount you should use the stack instead, e.g.: c[100], but that came up in the comments, too. You also need only one piece of memory. Here is a working example based on your code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// ALL CHECKS OMMITTED!
char *countAndSay(int A)
{
int k, count, j;
// "i" gets compared against the output of
// strlen() which is of type size_t
size_t i;
char a;
// Seed needs two bytes of memory
char *c = malloc(2);
// Another pointer, pointing to the same memory later.
// Set to NULL to avoid an extra malloc()
char *temp = NULL;
// a temporary pointer needed for realloc()-ing
char *cp;
// fill c with seed
c[0] = '1';
c[1] = '\0';
if (A == 1) {
return c;
}
// assuming 1-based input, that is: the first
// entry of the sequence is numbered 1 (one)
for (k = 2; k <= A; k++) {
// Memory needed is twice the size of
// the former entry at most.
// (Averages to Conway's constant but that
// number is not usable here, it is only a limit)
cp = realloc(temp, strlen(c) * 2 + 1);
temp = cp;
for (i = 0, j = 0; i < strlen(c); i++) {
//printf("A i = %zu, j = %zu\n",i,j);
a = c[i];
count = 1;
i++;
while (c[i] != '\0') {
if (c[i] == a) {
count++;
i++;
} else {
i--;
break;
}
}
temp[j++] = count + '0';
temp[j++] = a;
//printf("B i = %zu, j = %zu\n",i,j-1)
//printf("B i = %zu, j = %zu\n",i,j);
}
temp[j] = '\0';
if (k < A) {
// Just point "c" to the new sequence in "temp".
// Why does this work and temp doesn't overwrite c later?
// Or does it *not* always work and fails at one point?
// A mystery! Try to find it out! Some hints in the code.
c = temp;
temp = NULL;
}
// intermediate results:
//printf("%s\n\n",c);
}
return temp;
}
int main(int argc, char **argv)
{
// your code goes here
char *c = countAndSay(atoi(argv[1]));
printf("%s\n", c);
free(c);
return 0;
}
To get a way to check for sequences not in the list over at OEIS, I rummaged around in my attic and found this little "gem":
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
char *conway(char *s)
{
char *seq;
char c;
size_t len, count, i = 0;
len = strlen(s);
/*
* Worst case is twice as large as the input, e.g.:
* 1 -> 11
* 21 -> 1211
*/
seq = malloc(len * 2 + 1);
if (seq == NULL) {
return NULL;
}
while (len) {
// counter for occurrences of ...
count = 0;
// ... this character
c = s[0];
// as long as the string "s"
while (*s != '\0' && *s == c) {
// move pointer to next character
s++;
// increment counter
count++;
// decrement the length of the string
len--;
}
// to keep it simple, fail if c > 9
// but that cannot happen with a seed of 1
// which is used here.
// For other seeds it might be necessary to
// use a map with the higher digits as characters.
// If it is not possible to fit it into a
// character, the approach with a C-string is
// obviously not reasonable anymore.
if (count > 9) {
free(seq);
return NULL;
}
// append counter as a character
seq[i++] = (char) (count + '0');
// append character "c" from above
seq[i++] = c;
}
// return a proper C-string
seq[i] = '\0';
return seq;
}
int main(int argc, char **argv)
{
long i, n;
char *seq0, *seq1;
if (argc != 2) {
fprintf(stderr, "Usage: %s n>0\n", argv[0]);
exit(EXIT_FAILURE);
}
// reset errno, just in case
errno = 0;
// get amount from commandline
n = strtol(argv[1], NULL, 0);
if ((errno == ERANGE && (n == LONG_MAX || n == LONG_MIN))
|| (errno != 0 && n == 0)) {
fprintf(stderr, "strtol failed: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
if (n <= 0) {
fprintf(stderr, "Usage: %s n>0\n", argv[0]);
exit(EXIT_FAILURE);
}
// allocate space for seed value "1" plus '\0'
// If the seed is changed the limit in the conway() function
// above might need a change.
seq0 = malloc(2);
if (seq0 == NULL) {
fprintf(stderr, "malloc() failed to allocate a measly 2 bytes!?\n");
exit(EXIT_FAILURE);
}
// put the initial value into the freshly allocated memory
strcpy(seq0, "1");
// print it, nicely formatted
/*
* putc('1', stdout);
* if (n == 1) {
* putc('\n', stdout);
* free(seq0);
* exit(EXIT_SUCCESS);
* } else {
* printf(", ");
* }
*/
if (n == 1) {
puts("1");
free(seq0);
exit(EXIT_SUCCESS);
}
// adjust count
n--;
for (i = 0; i < n; i++) {
// compute conway sequence as a recursion
seq1 = conway(seq0);
if (seq1 == NULL) {
fprintf(stderr, "conway() failed, probably because malloc() failed\n");
exit(EXIT_FAILURE);
}
// make room
free(seq0);
seq0 = NULL;
// print sequence, comma separated
// printf("%s%s", seq1, (i < n - 1) ? "," : "\n");
// or print sequence and length of sequence, line separated
// printf("%zu: %s%s", strlen(seq1), seq1, (i < n-1) ? "\n\n" : "\n");
// print the endresult only
if (i == n - 1) {
printf("%s\n", seq1);
}
// reuse seq0
seq0 = seq1;
// not necessary but deemed good style by some
// although frowned upon by others
seq1 = NULL;
}
// free the last memory
free(seq0);
exit(EXIT_SUCCESS);
}

making an array-based program work with no elements

The exercise it to take an array of strings and, using pointers, concatenate them in a new string. I made it work by hard coding the values at each string array index, but I can't figure out how to make it work if the array has NO elements. I think I need to entirely restructure my code...
#include <stdio.h>
#include <stdlib.h>
int main(int argc, const char * argv[]) {
char *newArray[3];
//original code didn't have newArray as a pointer, and had the following:
//char *firstString = &newArray[0]; This was pointing to the value at the address of newArray[0] which was null at this point in time
//firstString = "Knicks"; This was reassigning the value of firstString to "Knicks" instead of pointing to the value located at the proper index address.
//this code correctly assigns values to each index of the array (which itself is just a pointer that is pointing to these values
newArray[0] = "Knicks";
newArray[1] = "Warriors";
newArray[2] = "Bulls";
//this code correctly assigns pointers that point to the index values of the array, which are all stated above.
char *firstString = newArray[0];
char *secondString = newArray[1];
char *thirdString = newArray[2];
int firstStringCount = 0;
int secondStringCount = 0;
int thirdStringCount = 0;
//count length of first element
for (int i = 0; i < 1000; i++) {
if (firstString[i] == '\0') {
break;
}
else {
firstStringCount++;
}
}
//count length of second element
for (int i = 0; i < 1000; i++) {
if (secondString[i] == '\0') {
break;
}
else {
secondStringCount++;
}
}
//count length of third element
for (int i = 0; i < 1000; i++) {
if (thirdString[i] == '\0') {
break;
}
else {
thirdStringCount++;
}
}
//int len = firstStringCount + secondStringCount + thirdStringCount;
char *concatenatedString = malloc(firstStringCount + secondStringCount + thirdStringCount);
for (int i = 0; i < firstStringCount; i++) {
concatenatedString[i] = firstString[i];
}
for (int i = 0; i < secondStringCount; i++) {
concatenatedString[i+firstStringCount] = secondString[i];
}
for (int i = 0; i < thirdStringCount; i++) {
concatenatedString[i+firstStringCount+secondStringCount] = thirdString[i];
}
//add in null value
concatenatedString[firstStringCount + secondStringCount + thirdStringCount] = '\0';
printf("%s\n", concatenatedString);
printf("%i\n", firstStringCount);
printf("%i\n", secondStringCount);
printf("%i\n", thirdStringCount);
return 0;
}
Your program will work when you have empty strings. This is not the same as having no array elements, because there must still be a \0 terminator in each, such as would be created with
newArray[0] = "";
But you have not allocated enough memory for the destination's string terminator. By using a 1 +
char *concatenatedString = malloc(1 + firstStringCount + secondStringCount +
thirdStringCount);
you now have room for the terminator with
concatenatedString[firstStringCount + secondStringCount + thirdStringCount] = '\0';

Pushing characters in char array to index 0

I'm trying to build a string from f, being split at whitespace and read it into a struct.
f is the char array I'm iterating over.
I then copy the contents from tmp into ra1.callsign, and essentially empty the tmp char array.
What I want to do is have the the tmp variable start building from index 0 again, so that when I try to strcpy the second time round all the characters in tmp start from index 0.
The way I have it now, when it tries the line: strcpy(ra1.location, tmp) it doesn't copy anything, I think this is because at that point the first character in tmp doesn't appear until some time down the array.
char c;
char tmp[1000];
for (i = 0; i < len; ++i) {
c = f[i];
if (c != ' ') {
tmp[i] = c; //build string to be added
}
//add string to data structure
if (c == ' ') {
if (addTo == CALLSIGN) {
strncpy(ra1.callsign, tmp, strlen(tmp));
memset(tmp, '\0', strlen(tmp));
}
if (addTo == LOCATION) {
strcpy(ra1.location, tmp);
}
++addTo;
}
}
Hope this is clear enough, thanks.
You left out quite a few details in your code and I have made a number of assumptions.
So, using the assumptions that I have made (which you can see in the code below), I believe that this will do what you are trying to accomplish. There are much easier and cleaner ways to do this, but I am hoping that you can get a clear understanding of how it would work with your code.
I have basically added a terminating null character where it is required so the strlen() function will work correctly and utilized an extra variable called cur_size which can be used as an offset based on the current index i.
#include <string.h>
#include <stdio.h>
#define CALLSIGN 3U
#define LOCATION 5U
#define ARRAY_SIZE 50U
typedef struct
{
char callsign[ARRAY_SIZE];
char location[ARRAY_SIZE];
} MyStruct;
MyStruct ra1 = { .callsign = {0}, .location = {0} };
char f[] = "This is my character array. Let's see what happens.";
int main (void)
{
char c;
char tmp[ARRAY_SIZE];
unsigned char addTo = 0;
unsigned char i;
unsigned char cur_size = 0;
for(i = 0; i < sizeof(f); ++i)
{
c = f[i];
if(c != ' ')
{
tmp[i - cur_size] = c; //build string to be added
}
//add string to data structure
if(c == ' ')
{
tmp[i - cur_size] = '\0'; /* YOU NEED THIS FOR strlen(tmp) to work */
cur_size = i + 1;
if(addTo == CALLSIGN)
{
strncpy(ra1.callsign, tmp, strlen(tmp));
//memset(tmp, '\0', strlen(tmp));
}
else if (addTo == LOCATION)
{
strncpy(ra1.location, tmp, strlen(tmp));
}
++addTo;
}
}
for (i = 0; i < ARRAY_SIZE; i++)
{
printf("%c", ra1.callsign[i]);
}
printf("\r\n");
for (i = 0; i < ARRAY_SIZE; i++)
{
printf("%c", ra1.location[i]);
}
printf("\r\n");
return 0;
}

Resources