Assigning new values to an array of C strings using pass by pointer method does not work properly.
Inside the "LettersToCapital" method, new values are assigned to the C-string array properly, however, once the C-strings array contents are read outside the method the results are all wrong. All the function is supposed to do is to capitalize all the lowercase letters. I am definitely doing something wrong, but what could it be?
If on line 53 variable tempStr is replaced with a constant string literal e.g. "aqua" then the values remain the same outside the function. But assigning directly from a char array (tempStr) to char array pointer (*(string +i)) does not yield correct results.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void LettersToCapital(char **string, int size);
void ReadOutAOC(char **string, int size);
int main()
{
char *canadianProvinces[] = {"British Columbia", "Alberta", "Saskatchewan", "Manitoba", "Ontario", "Quebec", "New Brunswick", "Nova Scotia", "Prince Edward Island", "Newfoundland", "Yukon", "Northwest Territories", "Nunavut"};
int numOfCanProv = sizeof(canadianProvinces) / sizeof(int);
printf("\nNumber of Canadian provinces %d\n", numOfCanProv);
// printing all provinces before conversion
printf("\nBefore \"all to capital conversion\"\n\n");
ReadOutAOC(canadianProvinces, numOfCanProv);
LettersToCapital(canadianProvinces, numOfCanProv);
// Temp(canadianProvinces);
// printing all provinces after conversion
printf("\nAfter \"all to capital conversion\"\n");
ReadOutAOC(canadianProvinces, numOfCanProv);
}
void ReadOutAOC(char **string, int size)
{
printf("\n");
for(int i = 0; i < size; i++)
printf("String outside the assignment method[%d]: %s\n", i + 1, *(string + i));
}
void LettersToCapital(char **string, int size)
{
char tempStr[256];
for(int i = 0; i < size; i++)
{
for(int j = 0; j < strlen(*(string + i)); j++)
{
if(*(*(string + i) + j) > 96 && *(*(string + i) + j) < 123)
tempStr[j] = *(*(string + i) + j) - 32;
else
tempStr[j] = *(*(string + i) + j);
}
tempStr[strlen(*(string + i))] = '\0';
*(string + i) = tempStr; // does not work
//*(string + i) = "aqua"; // try this instead
printf("String inside the assignment method[%d]: %s\n", i + 1, *(string + i));
}
}
Expected output should be:
Before "all to capital conversion"
British Columbia
Alberta
Saskatchewan
...
After "all to capital conversion"
BRITISH COLUMBIA
ALBERTA
SASKATCHEWAN
...
The following code:
ctype.h
and function: toupper()
char tempStr[256];
and all references to that variable are eliminatedAnd now the faulty code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
void LettersToCapital(char **string, size_t size);
void ReadOutAOC(char **string, size_t size);
int main( void )
{
char *canadianProvinces[] =
{
"British Columbia",
"Alberta",
"Saskatchewan",
"Manitoba",
"Ontario",
"Quebec",
"New Brunswick",
"Nova Scotia",
"Prince Edward Island",
"Newfoundland",
"Yukon",
"Northwest Territories",
"Nunavut"
};
size_t numOfCanProv = sizeof(canadianProvinces) / sizeof(canadianProvinces[0]);
printf("\nNumber of Canadian provinces %lu\n", numOfCanProv);
// printing all provinces before conversion
printf("\nBefore \"all to capital conversion\"\n\n");
ReadOutAOC(canadianProvinces, numOfCanProv);
LettersToCapital(canadianProvinces, numOfCanProv);
// Temp(canadianProvinces);
// printing all provinces after conversion
printf("\nAfter \"all to capital conversion\"\n");
ReadOutAOC(canadianProvinces, numOfCanProv);
}
void ReadOutAOC(char **string, size_t size)
{
printf("\n");
for( size_t i = 0; i < size; i++)
printf("String outside the assignment method[%lu]: %s\n", i + 1, string[i] );
}
void LettersToCapital(char **string, size_t size)
{
for( size_t i = 0; i < size; i++)
{
size_t j;
for( j = 0; j < strlen( string[i] ); j++)
{
string[i][j] = (char)toupper( string[i][j] );
}
printf("String inside the assignment method[%lu]: %s\n", i + 1, string[i] );
}
}
Running the above code results in the following output:
Before "all to capital conversion"
String outside the assignment method[1]: British Columbia
String outside the assignment method[2]: Alberta
String outside the assignment method[3]: Saskatchewan
String outside the assignment method[4]: Manitoba
String outside the assignment method[5]: Ontario
String outside the assignment method[6]: Quebec
String outside the assignment method[7]: New Brunswick
String outside the assignment method[8]: Nova Scotia
String outside the assignment method[9]: Prince Edward Island
String outside the assignment method[10]: Newfoundland
String outside the assignment method[11]: Yukon
String outside the assignment method[12]: Northwest Territories
String outside the assignment method[13]: Nunavut
Segmentation fault (core dumped)
using gdb to step through the program shows the cause of the seg fault event is this line:
string[i][j] = (char)toupper( string[i][j] );
because it is trying to change a value/byte/char in readonly memory
Suggest modifying the definition of the data to:
#define MAX_PROV_NAME_LEN 50
char canadianProvinces[][ MAX_PROV_NAME_LEN ] =
{
"British Columbia",
"Alberta",
"Saskatchewan",
"Manitoba",
"Ontario",
"Quebec",
"New Brunswick",
"Nova Scotia",
"Prince Edward Island",
"Newfoundland",
"Yukon",
"Northwest Territories",
"Nunavut"
};
Then adjusting the rest of the code to match would correct the problem.
The corrected code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAX_PROV_NAME_LEN 50
void LettersToCapital(char string[][ MAX_PROV_NAME_LEN ], size_t size);
void ReadOutAOC(char string[][ MAX_PROV_NAME_LEN ], size_t size);
int main( void )
{
char canadianProvinces[][ MAX_PROV_NAME_LEN ] =
{
"British Columbia",
"Alberta",
"Saskatchewan",
"Manitoba",
"Ontario",
"Quebec",
"New Brunswick",
"Nova Scotia",
"Prince Edward Island",
"Newfoundland",
"Yukon",
"Northwest Territories",
"Nunavut"
};
size_t numOfCanProv = sizeof(canadianProvinces) / sizeof(canadianProvinces[0]);
printf("\nNumber of Canadian provinces %lu\n", numOfCanProv);
// printing all provinces before conversion
printf("\nBefore \"all to capital conversion\"\n\n");
ReadOutAOC(canadianProvinces, numOfCanProv);
LettersToCapital(canadianProvinces, numOfCanProv);
// Temp(canadianProvinces);
// printing all provinces after conversion
printf("\nAfter \"all to capital conversion\"\n");
ReadOutAOC(canadianProvinces, numOfCanProv);
}
void ReadOutAOC(char string[][ MAX_PROV_NAME_LEN ], size_t size)
{
printf("\n");
for( size_t i = 0; i < size; i++)
printf("String outside the assignment method[%lu]: %s\n", i + 1, string[i] );
}
void LettersToCapital(char string[][ MAX_PROV_NAME_LEN ], size_t size)
{
for( size_t i = 0; i < size; i++)
{
size_t j;
for( j = 0; j < strlen( string[i] ); j++)
{
string[i][j] = (char)toupper( string[i][j] );
}
printf("String inside the assignment method[%lu]: %s\n", i + 1, string[i] );
}
}
a run of the corrected code results in the following output:
Number of Canadian provinces 13
Before "all to capital conversion"
String outside the assignment method[1]: British Columbia
String outside the assignment method[2]: Alberta
String outside the assignment method[3]: Saskatchewan
String outside the assignment method[4]: Manitoba
String outside the assignment method[5]: Ontario
String outside the assignment method[6]: Quebec
String outside the assignment method[7]: New Brunswick
String outside the assignment method[8]: Nova Scotia
String outside the assignment method[9]: Prince Edward Island
String outside the assignment method[10]: Newfoundland
String outside the assignment method[11]: Yukon
String outside the assignment method[12]: Northwest Territories
String outside the assignment method[13]: Nunavut
String inside the assignment method[1]: BRITISH COLUMBIA
String inside the assignment method[2]: ALBERTA
String inside the assignment method[3]: SASKATCHEWAN
String inside the assignment method[4]: MANITOBA
String inside the assignment method[5]: ONTARIO
String inside the assignment method[6]: QUEBEC
String inside the assignment method[7]: NEW BRUNSWICK
String inside the assignment method[8]: NOVA SCOTIA
String inside the assignment method[9]: PRINCE EDWARD ISLAND
String inside the assignment method[10]: NEWFOUNDLAND
String inside the assignment method[11]: YUKON
String inside the assignment method[12]: NORTHWEST TERRITORIES
String inside the assignment method[13]: NUNAVUT
After "all to capital conversion"
String outside the assignment method[1]: BRITISH COLUMBIA
String outside the assignment method[2]: ALBERTA
String outside the assignment method[3]: SASKATCHEWAN
String outside the assignment method[4]: MANITOBA
String outside the assignment method[5]: ONTARIO
String outside the assignment method[6]: QUEBEC
String outside the assignment method[7]: NEW BRUNSWICK
String outside the assignment method[8]: NOVA SCOTIA
String outside the assignment method[9]: PRINCE EDWARD ISLAND
String outside the assignment method[10]: NEWFOUNDLAND
String outside the assignment method[11]: YUKON
String outside the assignment method[12]: NORTHWEST TERRITORIES
String outside the assignment method[13]: NUNAVUT