Can't convert lowercase to uppercase with pointer - c

So I want to make lowercase letters to uppercase with one condition, before the lowercase letter there must be space, but the problem is I can't
check if the next char in the array(using +1) is a space or not.
#include <stdio.h>
#include <ctype.h>
void convertToUpper( char *array );
int main()
{
char x[] = "i believe i can do it";
convertToUpper(x);
printf("%s",x);
return 0;
}
void convertToUpper( char *array )
{
while( *array != '\0' )
{
if( *( array + 1 ) != ' ' && *array == ' ' )
{
*( ++array) = toupper( *(array) );
}
++array;
}
}

You are simply convert the wrong character, because in your condition, *array is space, you should convert the letter after it:
while(*array != '\0')
{
if( *(array + 1) != ' ' && *array == ' ')
*(array + 1) = toupper(*(array + 1));
++array;
}
This simple check won't work for the 1st char, if it should be upper case too, add following before the loop:
if (*array != ' ')
*array = toupper(*array)

void convertToUpper( char *array )
{
while ( array[0] != 0) && (array[1] != 0) )
{
if( (array[1] != ' ') && (array[0] == ' ' )
array[1] = toupper( array[1] );
++array;
}
}

This way remembers the previous character
char previous = ' ';
while(*array != '\0') {
if(previous == ' ') {
*array = toupper(*array);
}
previous = *array++;
}
just after an answer accepted, but I post anyway.

Related

Splitting an array without an inbuilt function

The code below is meant to take an input string like My name is Smith and outputs
My
name
is
Smith
and also has to exclude things like: , . and space, just these three, but instead it outputs, I'm not allowed to use any thing like strlen or strtok
My
y
name
ame
me
e
is
s
Smith
mith
ith
th
h
I've searched for the error everywhere in the code and I can't seem to figure it out
int main()
{
int wordSize = 0;
char str[81];
char* ptr_to_word[81];
gets_s(str);
for (char* res_p = &(str[0]); *res_p != '\0'; res_p++) {
if ((*res_p != '.') || (*res_p != ',') || (*res_p != ' '))
{
ptr_to_word[wordSize] = res_p;
wordSize++;
}
}
if (wordSize == 0)
{
printf("no solution");
}
else
{
for (int i = 0; i < wordSize; i)
{
char* a = ptr_to_word[i];
while ((*a != '.') && (*a != ',') && (*a != ' ') && (*a != '\0'))
{
printf("%c", *a);
a++;
}
printf("\n");
}
}
return 0;
}
In the condition of the if statement within this loop
for (char* res_p = &(str[0]); *res_p != '\0'; res_p++) {
if ((*res_p != '.') || (*res_p != ',') || (*res_p != ' '))
{
ptr_to_word[wordSize] = res_p;
wordSize++;
}
}
you have to use the logical AND operator instead of the logical OR operator like
if ((*res_p != '.') && (*res_p != ',') && (*res_p != ' '))
Nevertheless the loop in any case is wrong because the variable wordSize does not count words but counts each character that is not equal to the characters listed in the if statement.
To output separate words there is no need to declare an array of pointers to starts of words. You can output each word as soon as its start is found.
Here is a very simple demonstrative program.
#include <stdio.h>
int main(void)
{
enum { N = 81 };
char s[N];
fgets( s, N, stdin );
for ( const char *p = s; *p; )
{
int wordSize = 0;
while ( *p && *p != '.' && *p != ',' && *p != ' ' && *p != '\t' && *p != '\n' )
{
++wordSize;
++p;
}
if ( wordSize )
{
printf( "%.*s\n", wordSize, p - wordSize );
}
else
{
++p;
}
}
return 0;
}
If to input "My name is Smith" then the program output might look like
My
name
is
Smith
I appended the list of delimiters with the tab character '\t' and the new line character '\n' that can be inserted in the input string by the function fgets.
First of all, this condition
if ((*res_p != '.') || (*res_p != ',') || (*res_p != ' ')
will always be true, think about it, *res_p is always not '.' OR not ','. However, if you change the operator to && your code will still produce the same result.
The first loop with || operator writes a pointer to every character in your input string to the array ptr_to_word, and ' 's and '.'s are not printed only because of a condition in the second loop.
If you change the operator to && like so,
if ((*res_p != '.') && (*res_p != ',') && (*res_p != ' ')
you will write all the pointers, except for the '.', ',' and ' ', into the array, e.g. ptr_to_word[0] will point to 'My name is Smith', ptr_to_word[1] to 'y name is Smith', etc.
I have made a few changes to your code so that it would work as intended.
void split_str(char *str)
{
int wordSize = 0;
char *ptr_to_word[81];
char *res_p = &(str[0]);
int i = 0;
for (; *res_p != '\0'; res_p++) {
if ((*res_p != '.') && (*res_p != ',') && (*res_p != ' '))
{
wordSize++;
}
else
{
ptr_to_word[i] = res_p - wordSize;
wordSize = 0;
i++;
}
}
ptr_to_word[i] = res_p - wordSize;
ptr_to_word[i + 1] = NULL;
if (i == 0)
{
printf("no solution\n");
}
else
{
for (int i = 0; ptr_to_word[i]; i++)
{
char* a = ptr_to_word[i];
while ((*a != '.') && (*a != ',') && (*a != ' ') && (*a != '\0'))
{
printf("%c", *a);
a++;
}
printf("\n");
}
}
}
int main() {
split_str("My name is Smith\n");
}
This way you are writing a new value to the pointer array only when dot, comma or a space is encountered. For all other chars, you just do wordSize++ to keep track of the length of the word. I used pointer arithmetic to move back to the start of the word (ptr_to_word[i] = res_p - wordSize;).
I have tried to make only minimal changes to your code, just enough to make it work. There are still things I would change to make it better, e.g. the first loop finishes when the '\0' is encountered. Most likely, the last word finishes with a '\0', not a '.' or a ' '. Thus, it won't be written to the ptr_to_word, and I had to manually write it after the loop. Also, you don't even need two loops, you can use the same pointer. arithmetic to output the word as soon as it is found. So I'd advise you to do. a self-code-review, and optimize it further.
Good luck!

How can i make first letter of all words in a string uppercase recursively? [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 3 years ago.
Improve this question
I wonder how can i make this. I don't want any iteration or isalpha() and toupper() functions. We want to use our own code to read input. We assume that user enters all characters lowercase. This is what i've tried so far:
define MAX_LENGTH 100
int read_line(char str[],int);
void capitalize(char[]);
int main (void){
char A[MAX_LENGTH];
printf("Enter a text \n");
read_line(A, MAX_LENGTH);
capitalize(A);
puts(A);
}
int read_line(char str[],int n){
int ch,i=0;
while ((ch = getchar()) != '\n'){
if(i<MAX_LENGTH)
str[i++] = ch;
}
str[i] = '\0';
return i;
}
void capitalize(char str[]){
int x = strlen(str);
static int i = 0;
if(str[i]=='\0')
return;
if(str[i-1]==' '|| i == 0)
str[i] -= 32;
i++;
return capitalize(&str[i]);
}
Output is like this:
Enter a text:
asdf sdf df
Asdf sdf df
What is wrong with my code?
You code is invalid. For example even the function read_line
int read_line(char str[],int n){
int ch,i=0;
while ((ch = getchar()) != '\n'){
if(i<MAX_LENGTH)
str[i++] = ch;
}
str[i] = '\0';
return i;
}
is incorrect at least because when i is equal to MAX_LENGTH -1 there is an access memory beyond the character array
str[i] = '\0';
That is the condition of the loop is initially written incorrectly.
As for the recursive function then it can look for example the following way.
#include <stdio.h>
int is_blank( char c )
{
return c == ' ' || c == '\t';
}
char * capitalize( char *s )
{
if ( *s )
{
int blank = is_blank( *s );
if ( !blank )
{
*s &= ~' ';
}
capitalize( s + 1 );
if ( !blank && !is_blank( *( s + 1 ) ) && *( s + 1 ) )
{
*( s + 1 ) |= ' ';
}
}
return s;
}
int main(void)
{
char s[] = "hello everybody. how do you do?";
puts( s );
puts( capitalize( s ) );
return 0;
}
The program output is
hello everybody. how do you do?
Hello Everybody. How Do You Do?
Here is a similar demonstrative program but with your fixed function read_line.
#include <stdio.h>
#define MAX_LENGTH 100
int is_blank( char c )
{
return c == ' ' || c == '\t';
}
char * capitalize( char *s )
{
if ( *s )
{
int blank = is_blank( *s );
if ( !blank )
{
*s &= ~' ';
}
capitalize( s + 1 );
if ( !blank && !is_blank( *( s + 1 ) ) && *( s + 1 ) )
{
*( s + 1 ) |= ' ';
}
}
return s;
}
size_t read_line( char *s, size_t n )
{
int ch;
size_t i = 0;
while ( i + 1 < n && ( ch = getchar() ) != EOF && ch != '\n' )
{
s[i++] = ch;
}
s[i] = '\0';
return i;
}
int main(void)
{
char s[MAX_LENGTH];
read_line( s, MAX_LENGTH );
puts( s );
puts( capitalize( s ) );
return 0;
}
If to enter the string
hello everybody. how do you do?
then the program output will be the same as shown above.
hello everybody. how do you do?
Hello Everybody. How Do You Do?
If the bit-wise operations is unclear for you then you can substitute this statement
for this statement
*s &= ~' ';
for this statement
*s -= 'a' - 'A';
and this statement
*( s + 1 ) |= ' ';
for this statement
*( s + 1 ) += 'a' - 'A';
If to use your approach to the implementation of a recursive function with a static variable then it will be interesting to you why your function does not work will not be?
Let's consider it ignoring the first statement with the call of strlen.
void capitalize(char str[]){
int x = strlen(str);
static int i = 0;
if(str[i]=='\0')
return;
if(str[i-1]==' '|| i == 0)
str[i] -= 32;
i++;
return capitalize(&str[i]);
}
First of all after the first call the function for one string you may not call it a second time for another string because the static variable i will not be already equal to 0.
The condition of the if statement should be written at least like
if ( i == 0 || str[i-1]==' ' )
that is the order of sub-expressions shall be changed.
The return statement shall not contain an expression
return capitalize(&str[i]);
you could just write
capitalize(&str[i]);
Nevertheless the initial value of the pointer str was changed. However within the function you are using the index i relative the initial value of str of the first call of the function.
And I am sure it is interesting to you how correctly to rewrite the function, is not it?
The function can look the following way as it is shown in the demonstrative program below.
#include <stdio.h>
#define MAX_LENGTH 100
int is_blank( char c )
{
return c == ' ' || c == '\t';
}
char * capitalize( char *s )
{
static size_t i = 0;
if ( *( s + i ) )
{
if ( !is_blank( s[i] ) && ( i == 0 || is_blank( s[i-1] ) ) )
{
s[i] -= 'a' - 'A';
}
++i;
capitalize( s );
--i;
}
return s;
}
size_t read_line( char *s, size_t n )
{
int ch;
size_t i = 0;
while ( i + 1 < n && ( ch = getchar() ) != EOF && ch != '\n' )
{
s[i++] = ch;
}
s[i] = '\0';
return i;
}
int main(void)
{
char s[MAX_LENGTH];
read_line( s, MAX_LENGTH );
puts( s );
puts( capitalize( s ) );
return 0;
}
I would write the following:
void capitalize(char* str) {
if (! *str) return; // job done
*str = toupper(*str); // capitalize "correctly"
capitalize(++str);
}
the main problem is that you're using index and recursion at the same time, simple recursive solution would be:
void capitalize(char* str, bool start){
if (!*str) return; // end as soon as \0 is met
if (start)
if (*str >= 'a' && *str <= 'z') *str = (*str - 'a') + 'A'; // capitalize latin letters
capitalize(str + 1, *str == ' '); // work with next symbol
}
should be called as capitalize(str, true)
Should do the job:
void capitalize(char *s)
{
while(1) {
while (*s==' ') s++; // skip spaces
if (!*s) return; // check for end
if ('a'<=*s && *s<='z') *s -= 32; // capitalize if needed
while (*s && *s!=' ') s++; // advance
} // loop
}
(I call this "Stupid Character Processing")

counting words of a string

As the title states, few things I must add to explain: " "/tab/","/"." are things that divide words in my situation, another note that there can be more the one space or dot coming one after the other
this is what I have
int countWords(char * str, int length){
int counter = 0;
for( int i = 0; i < length; i++){
if(( str[i] == " ") || ( str[i] == ".") || ( str[i] == ",")){
if(( str[i+1] != " ") || ( str[i+1] != ".") || (str[i+1] != ",")){
if(( str[i-1] != " ") || ( str[i-1] != ".") || (str[i-1] != ","))
counter++;
}
}
}
return counter;
}
I get an error saying that I can not compare int and a pointer, I do understand where that is coming from, but how can I get it to actually work?
Note* I can't use string.h
In expressions like this
str[i] == " "
^^^
you are trying to compare an object of type char with a string literal that is implicitly converted to the type char *.
You have to use a character constant instead of the string literal
str[i] == ' '
^^^
The enclosing if statements do not make sense. For example for i equal to 0 the expression str[i-1] tries to access memory beyond the string.
The first parameter of the function should be declared with qualifier const.
The function can look the following way as it is shown in the demonstrative program.
#include <stdio.h>
size_t countWords( const char *s )
{
size_t n = 0;
for (size_t i = 0; s[i] != '\0'; )
{
while (s[i] == ' ' ||
s[i] == '\t' ||
s[i] == '.' ||
s[i] == ',') ++i;
if (s[i] != '\0')
{
++n;
while ( s[i] != '\0' &&
! ( s[i] == ' ' ||
s[i] == '\t' ||
s[i] == '.' ||
s[i] == ',')) ++i;
}
}
return n;
}
int main( void )
{
char *s = " Hello\t, World...";
printf("%zu\n", countWords(s));
}
The program output is
2
Or the function's implementation can look like
size_t countWords(const char *s)
{
size_t n = 0;
while ( *s )
{
while (*s == ' ' ||
*s == '\t' ||
*s == '.' ||
*s == ',') ++s;
if ( *s )
{
++n;
while ( *s &&
!( *s == ' ' ||
*s == '\t' ||
*s == '.' ||
*s == ',' ) ) ++s;
}
}
return n;
}
A more general approach of declaring the function is the following
size_t countWords( const char *s1, const char *s2 );
where the string s2 specifies a set of word separators.
If you want to count word there is one fine example in K&R ANSI C. Try to write program like this.
#include <stdio.h>
#define IN 1 /* inside a word */
#define OUT 0 /* outside a word */
/* count lines, words, and characters in input */
main()
{
int c, nl, nw, nc, state;
state = OUT;
nl = nw = nc = 0;
while ((c = getchar()) != EOF)
{
++nc;
if (c == '\n')
++nl;
if (c == ' ' || c == '\n' || c = '\t')
state = OUT;
else if (state == OUT)
{
state = IN;
++nw;
}
}
printf("%d %d %d\n", nl, nw, nc);
}
Hope this helps. :) You can find the pdf of this book here.

C - Counting words in a string

i've been trying to do a function that counts the number of words in a string in C. However, in some casas (as the one in the example) it should return 0 and not 1... any ideas of what could be wrong?
#import <stdio.h>
int contaPal(char s[]) {
int r;
int i;
r = 0;
for (i = 0; s[i] != '\0'; i++) {
if (s[i] == '\n')
r = r + 0;
if (s[i] != ' ' && s[i + 1] == ' ' && s[i + 1] != '\0')
r++;
if (s[i] != ' ' && s[i + 1] == '\0') {
r++;
}
}
return r;
}
int main () {
char s[15] = { ' ', '\n', '\0' };
printf("Words: %d \n", (contaPal(s)));
return 0;
}
You should not treat '\n' differently from any other whitespace character.
Here is a simpler version:
#include <ctype.h>
#include <stdio.h>
int contaPal(const char *s) {
int count = 0, hassep = 1;
while (*s) {
if (isspace((unsigned char)*s) {
hassep = 1;
} else {
count += hassep;
hassep = 0;
}
s++;
}
return count;
}
int main(void) {
char s[] = " \n";
printf("Words: %d\n", contaPal(s));
return 0;
}
I suppose that the word is any sequence of characters excluding white space characters.
Your function returns 1 because for the supplied string when the new line character is encountered the variable r is increased due to this condition
if (s[i] != ' ' && s[i + 1] == '\0') {
r++;
}
So the function implementation is wrong.
It can be defined the following way as it is shown in the demonstrative program
#include <stdio.h>
#include <ctype.h>
size_t contaPal( const char s[] )
{
size_t n = 0;
while ( *s )
{
while ( isspace( ( unsigned char )*s ) ) ++s;
n += *s != '\0';
while ( *s && !isspace( ( unsigned char )*s ) ) ++s;
}
return n;
}
int main(void)
{
char s[] = { ' ', '\n', '\0' };
printf( "Words: %zu\n", contaPal( s ) );
return 0;
}
Its output as you expect is
Words: 0
A simple illustration using existing character test functions:
int main(void)
{
int cnt = 0;
int numWords = 0;
BOOL trap = 0; //start count only after seeing a word
char *sentence = "This is a sentence, too long.";
//char *sentence2 = " ";//tested for empty string also
while (*sentence != '\0')
{
if ( isalnum (*sentence) ) //word is found, set trap and start count
{
sentence++; //alpha numeric character, keep going
trap = 1;
}
else if ( (( ispunct (*sentence) ) || ( isspace(*sentence) )) && trap)
{ //count is started only after first non delimiter character is found
numWords++;
sentence++;
while(( ispunct (*sentence) ) || ( isspace(*sentence) ))
{ //handle sequences of word delimiters
sentence++;
}
}
else //make sure pointer is increased either way
{
sentence++;
}
}
return 0;
}
The line:
if (s[i] != ' ' && s[i + 1] == ' ' && s[i + 1] != '\0')
r++;
Exactly matches the case when you look on '\n'.
You should use if ... else if ....

How to insert multiple chars to the middle of a char array in c?

I'm stuck trying to figure out how I can loop through a char array such as
char line[50] = "this is a string";
and add an extra space every time
line[counter] == ' ';
Thus resulting in the string with all the spaces being twice as long.
At first you should count the number of blank characters and then copy backward the string.
For example
#include <stdio.h>
int main(void)
{
char s[50] = "this is a string";
puts( s );
size_t n = 0;
char *p = s;
do
{
if ( *p == ' ' ) ++n;
} while ( *p++ );
if ( n != 0 )
{
char *q = p + n;
while ( p != s )
{
if ( *--p == ' ' ) *--q = ' ';
*--q = *p;
}
}
puts( s );
return 0;
}
The program output is
this is a string
this is a string
A more efficient approach is the following
#include <stdio.h>
int main(void)
{
char s[50] = "this is a string";
puts( s );
size_t n = 0;
char *p = s;
do
{
if ( *p == ' ' ) ++n;
} while ( *p++ );
for ( char *q = p + n; q != p; )
{
if ( *--p == ' ' ) *--q = ' ';
*--q = *p;
}
puts( s );
return 0;
}
Here is a solution using another string:
#include <stdio.h>
int main(void) {
char line[50] = "this is a string";
char newline[100]; //the new string, i chose [100], because there might be a string of 50 spaces
char *pline = line;
char *pnewline = newline;
while (*pline != NULL) { //goes through every element of the string
*pnewline = *pline; //copies the string
if (*pline == ' ') {
*(++pnewline) = ' '; //adds a space
}
pline++;
pnewline++;
}
printf("%s", line);
printf("%s", newline);
return 0;
}
If you wouldn't wan't to use up memory, you could do all this with dynamic memory allocation and free() the "temporary" string. I didn't do that now, as you used an array aswell.

Resources