Can't get user input using getchar() and pointer notation in C - c

I'm changing a program from normal array notation to pure pointer notation and I can't receive user input using getchar() in a while loop. I printed out was the program was receiving and it output upside down question marks. I wasn't sure why this was happening because I never changed the variable type. The problem is in the second function to receive user input. Thank you for the help.
#include <stdio.h>
#include <stdlib.h>
/* Function prototypes */
void fillS1(char * x);
void fillS2(char * x, char * y, char z);
void strFilter(char * a, char * b, char c);
int main(int argc, const char * argv[])
{
char s1[42];
char s2[22];
char x = 0;
fillS2(s2, s1, x);
return 0;
}
/* Function to generate a random string of 40 uppercase letters */
void fillS1(char randomlyGeneratedString[])
{
char * pointerToRandom = randomlyGeneratedString;
int i;
for (i = 0; i < 40; i++) {
*(pointerToRandom + i) = 'A' + rand() % 26;
}
pointerToRandom[40] = (char)0;
//printf("This is the generated string %s\n", pointerToRandom);
}
/* Function to get user input of characters */
void fillS2(char userString[], char randomString[], char replacementCharacter)
{
char * pointerToUserString = userString;
char * pointerToRandom = randomString;
int i = 0;
int n = 0;
int capitalLetterCheck = 0;
char loopContinue = 0;
char copyString[42];
char * pointerToCopyString = copyString;
fillS1(pointerToRandom);
do {
/* For loop to copy the first randomly generated string */
for(i = 0; i < 42; i++)
*(pointerToCopyString + i) = *(pointerToRandom + i);
i = 0;
capitalLetterCheck = 0;
/* While loop to to get user input */
printf("Please enter at least 2 capital letters and a maximum of 20.\n");
while (((*(pointerToUserString + i)) = getchar() != '\n')) {
/* Counter to determine how many characters were entered */
i++;
}
i++;
*(pointerToUserString + i) = '\0';
//printf("This is the value if i %i", i);
//printf("This is the user's string %s", pointerToUserString);
/* Capital letter check */
for (n = 0; n < 20; n++) {
if (((*(pointerToUserString + i)) >= 'A') && (*(pointerToUserString + i) <= 'Z'))
{
capitalLetterCheck++;
}
}
if (i < 3) {
printf("You need at least two letters\n");
}
else if (i > 21){
printf("You cannot have more than twenty letters\n");
}
else if (capitalLetterCheck >= 2) {
puts(pointerToUserString);
printf("Enter a character to replace occuring letters.\n");
scanf("%c", &replacementCharacter);
getchar();
strFilter(pointerToCopyString, pointerToUserString, replacementCharacter);
}
else
printf("You must have 2 capital letters.\n");
printf("Would you like to enter another string (y/n)?\n");
loopContinue = getchar();
getchar();
} while (loopContinue != 'n' && loopContinue != 'N');
}
/* Function to replace letters with the character chosen by the user */
void strFilter(char a[], char b[], char c)
{
char * pointerToA = a;
char * pointerToB = b;
int i = 0;
int n = 0;
while (n < 20) {
for (i = 0; i < 40; i++) {
if ((*(pointerToA + i)) == *(pointerToB + n)){
*(pointerToA + i) = c;
}
}
i = 0;
n++;
}
puts(a);
}

The problem is this in the if statement:
(*(pointerToUserString + i)) = getchar() != '\n'
Assignment is an expression, with lower precedence than comparison. This means the above is the same as:
(*(pointerToUserString + i)) = (getchar() != '\n')
So (*(pointerToUserString + i)) gets assigned the value of the expression getchar() != '\n' which is not what you want.

Related

why can't my program recognize similar words in a string?

I want to write a program that will take an input T. In the next T lines, each line will take a string as an input. The output would be how many ways the string can be reordered.
#include <stdio.h>
#include <stdlib.h>
int main() {
int T, i, l, count = 1, test = 0, word = 0, ans;
char line[200];
scanf("%d", &T);
for (i = 0; i < T; i++) {
scanf(" %[^\n]", line);
l = strlen(line);
for (int q = 0; q < l; q++) {
if (line[q] == ' ') {
word++;
}
}
ans = fact(word + 1);
word = 0;
for (int j = 0; j < l; j++) {
for (int k = j + 1; k < l; k++) {
if (line[k] == ' ' && line[k + 1] == line[j]) {
int m = j;
int n = k + 1;
for (;;) {
if (line[m] != line[n]) {
break;
} else
if (line[m] == ' ' && line[n] == ' ') {
test = 1;
break;
} else {
m++;
n++;
}
}
if (test == 1) {
count++;
ans = ans / fact(count);
count = 0;
test = 0;
}
}
}
}
printf("%d\n", ans);
}
}
int fact(int n) {
if (n == 1) {
return 1;
} else {
return n * fact(n - 1);
}
}
Now, in my program,
my output is like this:
2
no way no good
12
yes no yes yes no
120
if T = 2 and the 1st string is no way no good, it gives the right output that is 12 (4!/2!). That means, it has identified that there are two similar words.
But in the 2nd input, the string is yes no yes yes no. that means 3 yes and 2 nos. So the and should be 5!/(3!2!) = 10. But why is the answer 120? and why can't it recognize the similar words?
The main problem in your duplicate detector is you test the end of word with if (line[m] == ' ' && line[n] == ' ') but this test fails to identify a duplicate that occurs with the last word because line[n] is '\0', not ' '.
Note these further problems:
you do not handle words that occur more than twice correctly: you should perform ans = ans / fact(count); only after the outer loop finishes. For example, if a word is present 3 times, it will be detected as 3 pairs of duplicates, effectively causing ans to be divided by 23 = 8, instead of 3! = 6.
you should protect against buffer overflow and detect invalid input with:
if (scanf(" %199[^\n]", line) != 1)
break;
the range of type int for ans is too small for a moderately large number of words: 13! is 6227020800, larger than INT_MAX on most systems.
The code is difficult to follow. You should consider parsing the line into an array of words and using a more conventional way of counting duplicates.
Here is a modified version using this approach:
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static int cmpstr(const void *p1, const void *p2) {
char * const *pp1 = p1;
char * const *pp2 = p2;
return strcmp(*pp1, *pp2);
}
unsigned long long factorial(int n) {
unsigned long long res = 1;
while (n > 1)
res *= n--;
return res;
}
int main() {
int T, i, n, begin, count;
unsigned long long ans;
char line[200];
char *words[100];
if (!fgets(line, sizeof line, stdin) || sscanf(line, "%d", &T) != 1)
return 1;
while (T --> 0) {
if (!fgets(line, sizeof line, stdin))
break;
n = 0;
begin = 1;
for (char *p = line; *p; p++) {
if (isspace((unsigned char)*p)) {
*p = '\0';
begin = 1;
} else {
if (begin) {
words[n++] = p;
begin = 0;
}
}
}
qsort(words, n, sizeof(*words), cmpstr);
ans = factorial(n);
for (i = 0; i < n; i += count) {
for (count = 1; i + count < n && !strcmp(words[i], words[i + count]); count++)
continue;
ans /= factorial(count);
}
printf("%llu\n", ans);
}
return 0;
}

I cannot add an offset to a char array, and is my method of receiving strings and ints from the command line optimal?

In the first for loop I am trying to add an offset to a char array and am not able to do so.
I also wanted input from the terminal so I wrote code that is a ** to argv[2] and used atoi() to convert a char from argv[1] to an int.
int main(int argc, char *argv[]) {
if(argc != 3) {
printf("Enter an integer followed by a string \n\n");
return 1;
}
int i;
int offset = atoi(argv[1]);
char **p_message;
p_message = &argv[2];
char encrypt[strlen(*p_message)];
printf("You Entered: %d, %s \n", offset, *p_message);
for(i = 0; i < strlen(*p_message); i++)
{
encrypt[i] = ((*p_message[i] + offset) % 26);
}
for(i = 0; i < strlen(*p_message); i++)
{
printf("%c", encrypt[i]);
}
return 0;
}
The main problem is that you are not making an alphabet adjustment before, and after, the modulus operation. I added the variable letter as an int so that the arithmetic won't overflow.
You could simplify the program by dropping one of the stars for **p_message. Also, you would normally allocate an array 1 longer than the string, to allow for a nul terminator, but here, you are not treating the char array as a string, so no need.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
if(argc != 3) {
printf("Enter an integer followed by a string \n\n");
return 1;
}
int i;
int offset = atoi(argv[1]);
char *p_message; // remove a *
p_message = argv[2]; // remove &
char encrypt[strlen(p_message)]; // remove *
int letter; // added
printf("You Entered: %d, %s \n", offset, p_message); // remove *
for(i = 0; i < strlen(p_message); i++) { // remove *
letter = p_message[i]; // remove *
if(letter >= 'a' && letter <= 'z') { // if lower case
letter = 'a' + ((letter - 'a') + offset) % 26;
}
else if(letter >= 'A' && letter <= 'Z') { // if upper case
letter = 'A' + ((letter - 'A') + offset) % 26;
}
encrypt[i] = letter;
}
for(i = 0; i < strlen(p_message); i++) { // remove *
printf("%c", encrypt[i]);
}
return 0;
}

How do you return a string array inside a recursive function or copy it?

I have a problem at the add2_recur function. I am trying to add up a single character digit within a string. But I do not know how to return a string to my main function so I can print out the result. I try using function pointer but i only return the first value of the string.
Any suggestion on how to do this would be helpful.
//check if string is valid
int digcheck_helper(char *theno, int start, int length) {
int charToInt = *(theno+start);
if(!((charToInt >= 48) &&(charToInt <= 57)))
return 0;
if(length == 0)
return 1;
return digcheck_helper(theno,start+1,length-1);
}
int digcheck(char *str, int start, int length) {
return digcheck_helper(string,start,length);
}
/**********************
****add recursive function**/
void add2_recur(char *num1, char *num2, int start, int carryDig) {
int singleChar1 = *(num1 + start), singleChar2 = *(num2 + start);
char *str = (char*) malloc(strlen(num1) + 2);
sum = singleChar1 + singleChar - 96;
if(carryDig == 1)
sum = sum + 1;
if(start < strlen(num1)) {
if(sum >= 10) {
sum = sum - 10;
str[start] = sum + 48;
carryDig = 1;
printf("sum of single digit is: %c\n", str[start]);
}
else if( sum < 10) {
str[start] = sum + 48;
carryDig = 0;
printf("sum of single digit is: %c\n", str[start]);
}
add2_recur(num1,num2,start+1,carryDig);
}
else if ((start == strlen(num1)) && (carryDig ==1)){
str[start+1] = 48;
printf("sum of single digit is: %c\n", str[start+1]);
}
}
void add2(char *n1, char *n2) {
add2_recur(n1,n2,0,0)
}
/*******************/
int main() {
char string1[20000], string2[20000], revStr1[20000], revStr2[20000];
int digit_1, digit_2, i;
printf("Enter first number >");
fgets(string1,20000,stdin);
string1[strlen(string1)-1] = '\0';
digit_1 = digcheck(string1,0,strlen(string1)-1);
//Check if string is valid integer
if(digit_1 = 0)
printf("This number is invalid\n");
else{
printf("Enter second number >");
fgets(string2,2000,stdin);
string2[strlen(string2)-1] = '\0';
digit_2 = digcheck(string2,0,strlen(string2-1);
if(digit_2 == 0)
printf("This number is invalid\n");
else
printf("1st num is %s\n2st num is %s\n", string1, string2);
}
// reverse string
for(i=0;i<strlen(string1);i++)
revStr1[i] = string1[(strlen(string1)-1) - i];
for(i=0;i,strlen(string2);i++)
revStr2[i] = string2[(strlen(string2) -1) - i];
// compare string and pass to add2
if(strlen(revStr1) < strlen(revStr2)) {
for(i = strlen(revStr1); i < strlen(revStr2); i++)
revStr1[i] = '0';
add2(revStr1,revStr2);
}
else if(strlen(revStr2) < strlen(revStr1)) {
for(i = strlen(revStr2); i < strlen(revStr1); i++)
revStr2[i] = '0';
add2(revStr1,revStr2);
}
else
add2(revStr1,revStr2);
return 0;
}
In C something like this is typically achieved by not returning the actual string. Instead you can just work with a pointer to a buffer passed to you. Use the actual return value to report status messages instead.
To not spoil the actual task for you, let's define a simple recursive function that will return a string with all non-alphanumerical characters being stripped:
#include <stdio.h>
#include <string.h>
int strip_stuff_rec(const char *input, char *output, unsigned int offset_input, unsigned offset_output) {
// Retrieve the character and move the offset
const char c = input[offset_input++];
if (c == '\0') { // Terminator; we're done!
// Terminate the output string
output[offset_output] = '\0';
return 1; // Signal success
}
// Character is alphanumeric?
if (isalnum(c)) {
// Append the character to our result and move the offset
output[offset_output++] = c;
}
// To have an error case, let's just pretend the string must not include #!
if (c == '#') {
return 0; // Signal an error
}
// Now handle the next position
return strip_stuff_rec(input, output, offset_input, offset_output);
}
int strip_stuff(const char *input, char *output) {
// Reset the output
output[0] = '\0';
// Start the recursive calls
return strip_stuff_rec(input, output, 0, 0);
}
int main(int argc, char **argv) {
// First let's set some input string
const char *input = "Hello World! -- I've had a wonderful day!";
// And we'll need a buffer for our result
char result[256];
// Now call the function and check the return value to determine
// whether it's been successful.
if (strip_stuff(input, result) == 0) {
printf("Some error happened!\n");
}
else {
printf("The stripped string is '%s'.\n", result);
}
}
this function:
void add2(char *n1, char *n2)
{
add2_recur(n1,n2,0,0)
}
this function has a couple of problems.
1) it will not compile because the statement that calls add2-recur()
is missing a trailing ';'
2) this function is not needed as add2_recur can be called directly
3) this is expected to add two numbers together ..
How is it to return the result?
It (probably) should be more like:
void add2(char *n1, char *n2, char *sum)
{
strcpy(sum, add2_recur(n1,n2,0,0) );
}
ok, i fix the code by creating a pointer function and storing the value into the str array by using malloc. I commented out the code. But it still only return the first element of the array to the main function from the heap. How do i get it to return the whole array?
//check if string is valid
int digcheck_helper(char *theno, int start, int length) {
int charToInt = *(theno+start);
if(!((charToInt >= 48) &&(charToInt <= 57)))
return 0;
if(length == 0)
return 1;
return digcheck_helper(theno,start+1,length-1);
}
int digcheck(char *str, int start, int length) {
return digcheck_helper(string,start,length);
}
/**********************
****add recursive function**/
char *add2_recur(char *num1, char *num2, int start, int carryDig) {
int singleChar1 = *(num1 + start), singleChar2 = *(num2 + start);
char *str = (char*) malloc(strlen(num1) + 2), sum;
sum = singleChar1 + singleChar - 96;
if(carryDig == 1)
sum = sum + 1;
if(start < strlen(num1)) {
if(sum >= 10) {
sum = sum - 10;
str[start] = sum + 48; //store value in each element of an array
carryDig = 1;
printf("sum of single digit is: %c\n", str[start]);
}
else if( sum < 10) {
str[start] = sum + 48; //store value in each element of an array
carryDig = 0;
printf("sum of single digit is: %c\n", str[start]);
}
add2_recur(num1,num2,start+1,carryDig);
}
else if ((start == strlen(num1)) && (carryDig ==1)){
str[start+1] = 49; // store value in each element of an array
printf("sum of single digit is: %c\n", str[start+1]);
}
return str;
}
/*******************/
int main() {
char string1[20000], string2[20000], revStr1[20000], revStr2[20000], *addResult;
int digit_1, digit_2, i;
printf("Enter first number >");
fgets(string1,20000,stdin);
string1[strlen(string1)-1] = '\0';
digit_1 = digcheck(string1,0,strlen(string1)-1);
//Check if string is valid integer
if(digit_1 = 0)
printf("This number is invalid\n");
else{
printf("Enter second number >");
fgets(string2,2000,stdin);
string2[strlen(string2)-1] = '\0';
digit_2 = digcheck(string2,0,strlen(string2-1);
if(digit_2 == 0)
printf("This number is invalid\n");
else
printf("1st num is %s\n2st num is %s\n", string1, string2);
}
// reverse string
for(i=0;i<strlen(string1);i++)
revStr1[i] = string1[(strlen(string1)-1) - i];
for(i=0;i,strlen(string2);i++)
revStr2[i] = string2[(strlen(string2) -1) - i];
// compare string and pass to add2
if(strlen(revStr1) < strlen(revStr2)) {
for(i = strlen(revStr1); i < strlen(revStr2); i++)
revStr1[i] = '0';
add2(revStr1,revStr2);
}
else if(strlen(revStr2) < strlen(revStr1)) {
for(i = strlen(revStr2); i < strlen(revStr1); i++)
revStr2[i] = '0';
addResult = add2(revStr1,revStr2);
}
else
addResult = add2(revStr1,revStr2);
// print out
printf("sum is: %s\n", addResult);
return 0;
Since passing the whole array is not very optimal, C usually in most of the expressions convert it to pointer.
One way to pass whole array is by enclosing it in a struct. (Not a good solution though)
typedef struct
{
char s[128];
}MYSTR;

Finding and counting uppercase and lowercase chars

I have written a program in C running on UNIX which counts the number of each letters in a input text file. For a file like this:
'The cat sat on the green mat'
The output would be like this:
The letter ’a’ occurs 3 times.
The letter ’c’ occurs 1 times.
The letter ’e’ occurs 4 times.
The letter ’g’ occurs 1 times.
The letter ’h’ occurs 2 times.
The letter ’m’ occurs 1 times.
The letter ’n’ occurs 2 times.
The letter ’o’ occurs 1 times.
The letter ’r’ occurs 1 times.
The letter ’s’ occurs 1 times.
The letter ’t’ occurs 5 times.
5 *
4 * *
4 * *
3 * * *
3 * * *
2 * * * * *
2 * * * * *
1 * * * ** *** ***
1 * * * ** *** ***
0 **************************
0 **************************
... abcdefghijklmnopqrstuvwxyz
Where the graph represents the amount of times a letter appears. (If it is more than 10, i simply put a '+' after the 10th row). The code I've currently written to achieve this is as follows:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
void drawGraph(int letters[26], char alpha[26]);
void printLetters(int letters[26], char alpha[26]);
void getLetters(FILE *fp, int letters[26], char alpha[26]);
int main(int argc, char *argv[]) {
FILE *fp;
int letters[26] = { 0 };
char alpha[26] = { 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z' };
int indexedAlpha[256] = { 0 };
int j = 1;
for (i = 97; i <= 127; i++)
{
indexedAlpha[i] = j;
j++;
}
//open file
if ((fp = fopen(argv[1], "r")) == NULL)
{
perror("Cannot open file");
exit(EXIT_FAILURE);
}
getLetters(fp, letters, alpha);
printLetters(letters, alpha);
printf("\n");
drawGraph(letters, alpha);
printf("\n");
return EXIT_SUCCESS;
}
void getLetters(FILE *fp, int letters[26], char alpha[26]) {
int c;
for (int i = 0; (c = fgetc(fp)) != EOF; i++)
{
c = fgetc(fp);
if ( isalpha(c) )
{
for ( int j = 0; j < 26; j++ ) //find which letter it is
{
if( c == alpha[j] )
{
letters[j]++;
break;
}
}
}
}
}
void printLetters(int letters[26], char alpha[26]) {
for( int i = 0; i < 26; i++ )
{
if(letters[i] != 0){
printf("The letter '%c' occurs %d times.\n", alpha[i], letters[i]);
}
}
}
void drawGraph(int letters[26], char alpha[26]) {
int x = 11;
int y;
while(x >= 0)
{
y = 0;
while (y < 2)
{
if (x == 10)
{
printf(" %d ", x);
}
else if (x == 11)
{
printf(" ");
}
else
{
printf(" %d ", x);
}
for( int i = 0; i < 26; i++ )
{
if(letters[i] > 10)
{
printf("+");
letters[i] = 10;
y++; // Break out of while loop
}
else if(letters[i] == x)
{
printf("*");
}
else
{
printf(" ");
}
if (letters[i] == x && y == 1)
{
letters[i] = letters[i] - 1;
}
}
printf("\n");
y++;
}
x--;
}
printf("... ");
for( int i = 0; i < 26; i++ )
{
printf("%c", alpha[i]);
}
}
However my current code has two problems.
1. I always print out 10 Y-axis points i want to only print out as many Y-axis points as needed, What would be the best way to achieve this?
2. Currently only lower case characters are counted, how can i address this?
Also any notation or better methodology would be much appreciated, Im still trying to learn!
Thanks!
2nd question seems bit easy to me :
2. Currently only lower case characters are counted, how can i address this?
make an structure like this :
typedef struct
{
char c;
int count;
}alpha;
alpha abc[26];
for(i=0 ; i<26 ; i++)
abc[i].count = 0; // Initialization of count for each alphabet
for(i=0;i<26; i++)
abc[i].c = 'a' + i;
In this way you can keep track of each letter with it's count.
To print "histogram" of each alphabet in file you need (11 + 1 + 1) lines
(means at least 13 lines , can be extra lines for separating characters and their bar )
11 lines for 11 times occurrence of alphabet and 1 for + as mentioned and 1 for alphabets itself.
But to print these lines, You need to take care of extra things about the space before the each of the *(histogram symbol you used).
So, loop through the array and print it like, For your 1st question try something like this:
int cnt;
for(cnt = 11 ; c >=0 ; c--)
{
for(i=0; i<26; i++)
{
if(abc[i].count >= cnt && cnt == 11)
{
space = abc[i].c - 'a';
printf("%*c",space,'+'); // setting indentation and printing
}
if(abc[i].count == cnt && cnt != 11)
{
space = abc[i].c - 'a';
printf("%*c",space,'*'); //// setting indentation and printing
}
printf("\n");
} //end of inner for loop
} // end of outer for loop
printf("abcdefghijklmnopqrstuvwxyz\n");
A different data representation would simplify your program.
Use one table to hold all possible one byte characters; the byte val of the char serves as key; # of occurences is val.
Note the use of while ((c = getchar()) != EOF); the idiom for reading input one byte at a time - your getLetters() routine skipped every other char.
The program below handles both upper and lowercase letters; but is restricted to one-byte encodings - it does not properly handle utf8, utf16 etcetera. For more info on text encodings read this article. What isalpha() treats as a letter depends on the current locale, which can by altered by setlocale
#include <stdio.h>
#include <ctype.h>
#include <limits.h>
enum { NROWS = 10 };
void draw_line(int count[], double scale, int level);
void draw(int count[]);
int main() {
int count[UCHAR_MAX+1] = {0};
int c;
while ((c = getchar()) != EOF)
count[c]++;
for (c = 0; c <= UCHAR_MAX; c++)
if (isalpha(c) && count[c] != 0)
printf("%c %d\n", c, count[c]);
draw(count);
return 0;
}
My draw graph version, scales the y values instead of printing '+' for large values. It prints out only as many "y-axis stars" as neeeded by comparing the count to the level of the y-axis.
void draw(int count[]) {
int c, i;
int max = 0;
double scale;
for (c = 0; c <= UCHAR_MAX; c++)
if (isalpha(c) && count[c] > max)
max = count[c];
scale = (max == 0) : 1.0 : (double)max / NROWS;
for (i = NROWS; i > 0; i--)
draw_line(count, scale, i);
for (c = 0; c <= UCHAR_MAX; c++)
if (isalpha(c))
putchar(c);
putchar('\n');
}
void draw_line(int count[], double scale, int level) {
int c;
for (c = 0; c <= UCHAR_MAX; c++) {
if (isalpha(c) && count[c] / scale >= level)
putchar('*');
else if (isalpha(c))
putchar(' ');
}
putchar('\n');
}
An example output of the graph:
$ ./countchars < countchars.c
[..snip..]
*
* *
* *
* * * *
* * * * *
* * * * * * *
* * * * * ** * **
* *** ** * ** * **
* * **** ** * *** ****
* * * * * * * * **** ** ***** ******
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz

I can't seem to figure out how to properly pass parameters with pure pointer notation

I'm trying to modify a previous program I wrote using pure pointer notation. It's a program that generates a random string of 40 uppercase letter, takes input of up to 20 uppercase letter, and input of a character. The program replaces reoccurring characters in the generated string with the character entered. Right now, I'm trying to pass the parameters of the randomly generated string so I can access them in the second function and can't figure out how to do it.
Thank you for the help.
#include <stdio.h>
#include <stdlib.h>
/* Function prototypes */
void fillS1(char * x);
void fillS2(char * x, char * y, char z);
void strFilter(char * a, char * b, char c);
int main(int argc, const char * argv[])
{
char s1[41];
char s2[21];
char x = 0;
char * pointerToS1;
char * pointerToS2;
pointerToS1 = s1;
pointerToS2 = s2;
fillS2(pointerToS2, pointerToS1, x);
return 0;
}
/* Function to generate a random string of 40 uppercase letters */
void fillS1(char * randomlyGeneratedPointer)
{
char randomlyGeneratedArray[41];
randomlyGeneratedPointer = randomlyGeneratedArray;
int i;
for (i = 0; i < 40; i++) {
*(randomlyGeneratedPointer + i) = 'A' + rand() % 26;
}
}
/* Function to get user input of characters */
void fillS2(char * userStringPointer, char * randomStringPointer, char replacementCharacter)
{
char userstring[21];
char randomString[41];
char copyString[42];
//char * pointerToCopyString = copyString;
userStringPointer = userstring;
int i = 0;
int n = 0;
int lowercaseCheck = 0;
char loopContinue = 0;
fillS1(randomStringPointer); //here is the function call for the randomly generated string.
printf("This is the random string: %s", randomStringPointer);
do {
/* For loop to copy the first randomly generated string */
for(i = 0; i < 42; i++)
*(randomStringPointer + i) = copyString[i];
randomStringPointer = copyString;
i = 0;
lowercaseCheck = 0;
/* While loop to to get user input */
printf("Please enter at least 2 capital letters and a maximum of 20.\n");
while ((((*(userStringPointer + i)) = getchar()) != '\n')) {
/* Counter to determine how many characters were entered */
i++;
}
/* Adding 1 to add to add null character */
i++;
*(userStringPointer + i) = '\0';
//printf("This is the user's string %s", userStringPointer);
/* Capital letter check */
for (n = 0; n < 20; n++) {
if (((*(userStringPointer + n)) >= 'a') && (*(userStringPointer + n) <= 'z')) {
lowercaseCheck++;
}
}
if (--i < 3) {
printf("You need at least two letters\n");
}
else if (i > 21){
printf("You cannot have more than twenty letters\n");
}
else if (lowercaseCheck == 0) {
puts(userStringPointer);
printf("Enter a character to replace occuring letters.\n");
scanf("%c", &replacementCharacter);
getchar();
//printf("this is the copy string before strFilter: %s", randomStringPointer);
//printf("This is the replacement character %c", replacementCharacter);
strFilter(randomStringPointer, userStringPointer, replacementCharacter);
}
else
printf("You must have 2 capital letters.\n");
printf("Would you like to enter another string (y/n)?\n");
loopContinue = getchar();
getchar();
} while (loopContinue != 'n' && loopContinue != 'N');
}
/* Function to replace letters with the character chosen by the user */
void strFilter(char * replacementCopyStringPointer, char * replacementUserStringPointer, char c)
{
int i = 0;
int n = 0;
while (n < 20) {
for (i = 0; i < 40; i++) {
if ((*(replacementCopyStringPointer + i)) == *(replacementUserStringPointer + n)){
*(replacementCopyStringPointer + i) = c;
}
}
i = 0;
n++;
}
puts(replacementCopyStringPointer);
}
randomlyGeneratedArray array in fillS1 would get destroyed once fillS1 function returns.
You should allocate the memory from heap for randomlyGeneratedArray.
randomlyGeneratedArray = (char *)malloc(sizeof(char)*41)
Also do the same for userStringPointer in fillS2.
That should solve the problem.
For difference between stack and heap read this question What and where are the stack and heap?

Resources