two dimensional array in c, reversing and storing a sentence - c

Hey I'm really new to programming and having trouble with arrays. Can someone help me with this project. "c programming a modern approach: modify a program that reverses the words of a sentence so that it stores the words in a two dimensional char array as it reads the sentence, with each row of the array storing a single word. assume that the sentence contains no more than 30 words and no word is more than 20 characters long. Be sure to store a null character at the end of each word so that it can be treated as a string"
(also i don't get what its saying about the null character).
here's my try but it's not working. i think i'm close though.
#include <stdio.h>
#define MAX_SENTENCE_LEN 80
#define SENTENCE_MAX 30
#define WORD_MAX 20
int main(void)
{
char ch, sentence[MAX_SENTENCE_LEN] = {' '}, terminator = '.';
int n, i, j, start, finish;
printf("Enter a sentence: ");
for (n = 1; n < MAX_SENTENCE_LEN; n++) {
ch = getchar();
if (ch == '.' || ch == '?' || ch == '!') {
terminator = ch;
break;
}
sentence[n] = ch;
}
printf("Reversal of sentence:");
finish = n;
for (start = finish - 1; start >= 0; start--) {
if (sentence[start] == ' ') {
for (i = start; i < finish; i++)
putchar(sentence[i]);
finish = start;
}
{
int sentence[SENTENCE_MAX][WORD_MAX];
int word[30][20];
for (i=0; i< SENTENCE_MAX;i++){
for (j=0; j<WORD_MAX; j++)
sentence[i][j]=-1;
}
}
}
printf("%c\n", terminator);
return 0;}
i wrote a new code which i think is closer to what i want but it still won't run. do i have a faulty compiler or what?
anyway here's the new code
#include<stdio.h>
#define N 100
int main (void)
{
char sentence[N][N], ch, termChar;
int i = 0, l = 0, count = 0;
int j = 0, k, start, finish, word;
printf("enter a sentence: ");
while (ch = getchar())
{
sentence[i][l++]= ch;
if (ch == ' ')
{
sentence[i][l] = '\0';
i++;
l = 0;
count++;
}
if (ch == '.' || ch == '!' || ch == '?')
{
sentence[i][l-1]= ' ';
sentence[i][l]= '\0';
termChar = ch;
count ++;
break;
}
}
for(i=count ; i>=0; i--)
printf("%s ", sentence[i]);
printf("%c\n", termChar);
return 0;
}

Your code worked perfectly in my environment (Windows, C99 compiler, 32bit build). I entered a short sentence, and it reversed it:
Regarding: i don't get what its saying about the null character
a C string is defined by a null character: \0, at the end of a char array. example char string[]="word" looks like: |w|o|r|d|\0| in memory.
Without the \0, it would simply be a char array, but not a string, and would therefore not be useable in any of the string functions such as strcpy(), strlen(), etc.
By the way, sentence creation and initialization:
char sentence[MAX_SENTENCE_LEN] = {' '};
Does not guarantee contents for the entire length of the char array.
This may be the reason your environment is not running your code, while my environment does.
Depending on compiler, OS, and other random factors, sentence could be filled with anything. So, if your code is not running on your machine, it is likely that you just need to initialize sentence to \0. Replace that line with these:
char sentence[MAX_SENTENCE_LEN]; //create
memset(sentence, 0 ,MAX_SENTENCE_LEN); //zero all memory
sentence[0]=' '; //set first char to a space (' '). (not sure why)
Also by chance, if the user input results in string length == MAX_SENTENCE_LEN, then your program will crash as there is only enough room in sentence for MAX_SENTENCE_LEN-1 + \0.

#include <stdio.h>
#define MAX_SENTENCE_LEN 80
#define SENTENCE_MAX 30
#define WORD_MAX 20
int main(void){
char ch, sentence[MAX_SENTENCE_LEN] = {' '}, terminator = '.';
int n, i, j, start, finish;
char word[SENTENCE_MAX][WORD_MAX+1];
int wc=0, wcc=0;
printf("Enter a sentence: ");
for (n = 1; n < MAX_SENTENCE_LEN; n++) {
ch = getchar();
if (ch == '.' || ch == '?' || ch == '!') {
terminator = ch;
break;
} else if(ch != ' '){
word[wc][wcc++] = ch;
} else if(ch == ' '){//this is assumed to be one space between words.
word[wc++][wcc] = '\0';//null character
wcc = 0;
}
sentence[n] = ch;
}
word[wc++][wcc] = '\0';
printf("Reversal of sentence:");
finish = n;
for (start = finish - 1; start >= 0; start--) {
if (sentence[start] == ' ') {
for (i = start; i < finish; i++)
putchar(sentence[i]);
finish = start;
}
}
printf("%c\n", terminator);
for(i=wc-1;i>=0;--i){
printf("%s", word[i]);
if(i>0)
putchar(' ');
}
printf("%c\n", terminator);
return 0;
}

Related

Make first letter of every word capital after removing vowels

My code works to delete any vowels and prints the first letter of the word as a capital letter.
How can I get my expected output to work?
If the value is " I am Iron Man" (with a leading space), it works and prints "M Rn Mn".
However, without the space at the beginning of the string, my output is "m Rn Mn" but
the expected output is "M Rn Mn".
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char str[] = "I am Iron Man";
int i, j, len = 0;
len = strlen(str);
// Accepting input.
for (i = 0; i < len; i++) {
// Check vowels.
if (str[i] == 'a' || str[i] == 'e' || str[i] == 'i' || str[i] == 'o' || str[i] == 'u' ||
str[i] == 'A' || str[i] == 'E' || str[i] == 'I' || str[i] == 'O' || str[i] == 'U') {
// delete vowel syntax
for (j = i; j < len; j++) {
// Store after removing vowels
str[j] = str[j + 1];
}
i--;
len--;
}
str[len + 1] = '\0';
}
for(i=0; str[i]!='\0'; i++)
{
//check first character is lowercase alphabet
if(i==0)
{
if((str[i]>='a' && str[i]<='z'))
str[i]=str[i]-32; //subtract 32 to make it capital
continue; //continue to the loop
}
if(str[i]==' ')//check space
{
//if space is found, check next character
++i;
//check letter if lowercase
if(str[i]>='a' && str[i]<='z')
{
str[i]=str[i]-32; //subtract 32 to make it capital
continue; //continue to the loop
}
}
}
printf("%s", str);
return 0;
}
Your problem lies with excessive use of the continue statement in the second for loop. The second continue is just plain pointless, as control reaches the end of the loop, anyway, after the point where you have that.
But the first continue is actually causing the fault: after removal of the vowels, the first character in the modified string will be a space – so, the first if block inside the second loop will be entered, and that will skip the check for a lowercase letter following the space.
Removing those continue statement will fix your code.
Also, note that you can use the islower and toupper functiosn to check for lowercase letters and convert to uppercase:
#include <stdio.h>
#include <string.h>
#include <ctype.h> // For islower and toupper
int main()
{
char str[] = "I am Iron Man";
size_t i, j, len = 0;
len = strlen(str);
// Accepting input.
for (i = 0; i < len; i++)
{
// Check vowels.
if (str[i] == 'a' || str[i] == 'e' || str[i] == 'i' || str[i] == 'o' || str[i] == 'u' ||
str[i] == 'A' || str[i] == 'E' || str[i] == 'I' || str[i] == 'O' || str[i] == 'U') {
// delete vowel syntax
for (j = i; j < len; j++)
{
// Store after removing vowels
str[j] = str[j + 1];
}
i--;
len--;
}
str[len + 1] = '\0';
}
for (i = 0; str[i] != '\0'; i++)
{
//check first character is lowercase alphabet
if (i == 0)
{
if (islower(str[i])) {
str[i] = toupper(str[i]);
}
// A "continue" here is wrong ... it will skip the following check for a lowercase letter
}
if (str[i] == ' ') //check space
{
//if space is found, check next character
++i;
//check letter if lowercase
if (islower(str[i]))
{
str[i] = toupper(str[i]);
// No need for a "continue" here ... we're already at the end of the loop
}
}
}
printf("%s\n", str);
return 0;
}
I have another solution for you, that may be a bit easier to comprehend:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main(void) {
char str[] = "I am Iron Man";
char *in;
char *out;
int up = 1; // very simple state, if "up" then next character should be made upper
for (in = str, out = str; *in; in++) {
if (strchr("aeiouAEIOU", *in) != NULL) {
// do nothing
} else if (*in == ' ') {
*out++ = *in;
up = 1; // we see a space, so next letter should be upper
} else if (up) {
*out++ = toupper(*in);
up = 0; // we see a letter (or other character), ignore case
} else {
*out++ = *in;
}
}
*out = '\0';
printf("%s\n", str);
}
Or, if you don't like/understand the pointer syntax:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main(void) {
char str[] = "I am Iron Man";
int i;
int o;
int up = 1; // very simple state, if "up" then next character should be made upper
for (i = 0, o = 0; str[i]; i++) {
if (strchr("aeiouAEIOU", str[i]) != NULL) {
// do nothing
} else if (str[i] == ' ') {
str[o++] = str[i];
up = 1; // we see a space, so next letter should be upper
} else if (up) {
str[o++] = toupper(str[i]);
up = 0; // we see a letter (or other character), ignore case
} else {
str[o++] = str[i];
}
}
str[o] = '\0';
printf("%s\n", str);
}
In both cases, a very simple state is used. For more complex conditions, you should learn about state machines. In this case, the up state indicates that the next letter should be capitalised.
Note that if you want to remove leading spaces, after "removing" the vowels, you need to modify the logic a bit:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main(void) {
char str[] = "I am Iron Man";
char *in = str; // we initialize in and out here already
char *out = str;
int up = 1; // very simple state, if "up" then next chacter should be made upper
// we skip leading vowels AND spaces, this is a special case
while (*in && (strchr("aeiouAEIOU ", *in) != NULL)) {
in++;
}
// now we are at the first character that is not a vowel or space
for ( ; *in; in++) {
if (strchr("aeiouAEIOU", *in) != NULL) {
// do nothing
} else if (*in == ' ') {
*out++ = *in;
up = 1; // we see a space, so next letter should be upper
} else if (up) {
*out++ = toupper(*in);
up = 0; // we see a letter (or other character), ignore case
} else {
*out++ = *in;
}
}
*out = '\0';
printf("%s\n", str);
}
Well now you have a few examples to study that take a bit of a different approach. See if you understand the logic, and try to make it so that other characters like e.g. ( and ) also delimit words.
One of the problems is that you've got too much code. It iterates through the entire array once to strip out vowels, then again to adjust the case of the first letter of each word. Imagine this is processing data that is measured in Gb. A second pass is unnecessary.
(And, there are standard library functions like isalpha() and toupper() that you should use. Don't write code with "magic numbers".)
It's worth studying a program's 'flow control', without resorting to arbitrary 'continue' statements to affect that flow.
It's also worth starting from scratch with a minimal block of code in main(), then developing your algorithm in a function (or several). Avoid the tendency to have one long, linear program all inside main(). If you can put functionality into 'compartments', each can be developed and tested and forgotten about as the program grows more complex.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
// A single pass "compacts" the data (no vowels) while also using some single operations
//tracking changing from one word to the next (first letter to uppercase.)
char *func( char *str ) {
for ( int d = 0, s = 0, up = 0; (str[d] = str[s]) != '\0'; s++)
if( !strchr( " aeiouAEIOU" + !!up, str[d] ) ) {
if( str[d] == ' ' )
up = 1;
else if( up++ < 2 )
up++, str[d] = (char)toupper( (unsigned char)str[d] );
d++; // 'd'estination idx only increments here!
}
return str;
}
int main(void) {
// sample test strings
char *strs[] = {
"I am Iron Man",
" I am Iron Man ",
"Iron Man am I",
" Iron Man am I",
"The man of steel",
" The man of steel",
};
for( size_t i = 0; i < sizeof strs/sizeof strs[0]; i++ )
puts( func( strs[i] ) );
return 0;
}
M Rn Mn
M Rn Mn
Rn Mn M
Rn Mn M
Th Mn F Stl
Th Mn F Stl

Finding palindrome in C

A palindrome is a word that reads the same from left to right and from right to left.
I wrote a program that finds palindromes from a console.
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#define SIZE 100
int main() {
int i = 0, c;
int left, right;
char string[SIZE];
while (EOF != (c = getchar()) || (c = getchar()) != '\n') {
if (isspace(c) != 0) {
if (i > 0) {
left = 0;
right = i - 1;
while (right > left) {
if (string[left] != string[right]) {
i = 0;
break;
}
++left;
--right;
}
if (left >= right) {
while (i > 0)
printf("%c", string[--i]);
printf("%c", c);
}
i = 0;
}
if (c == '\n')
break;
}
else {
string[i++] = c;
}
}
}
For example, we enter the words: dad sad mum. She outputs: dad mum. But if we write dad sad or dad mum sad. The output will be: dad mum.
That is, an extra space is printed when the last word we read is not a palindrome. How can you get around this situation?
Code is convoluted
First read input properly and form a string.
for (i = 0; i < SIZE - 1; i++) [
int ch = getchar();
if (ch == EOF || ch == '\n') {
break;
}
string[i++] = (char) ch;
}
string[i] = 0;
Then process the string in string[]. Only print spaces when needed.
const char *separator = "";
int i = 0;
while (string[i]) {
// Beginning of a word?
if (!isspace(string[i])) {
int start = i;
int end = i;
while (!isspace(string[end+1]) && string[end+1]) {
end++;
}
// At this point, start indexes the 1st char of the word
// and end indexes the last char of the word
// Now find if a palindrome
while (start <= end && string[start] == string[end]) {
start++;
end--;
}
// Found a palindrome?
if (start > end) {
fputs(separator, stdout);
separator = " "; // print a space _next_ time
while (!isspace(string[i]) && string[i]) {
fputc(string[i++], stdout);
}
} else {
i = end + 1;
}
} else {
i++;
}
}
fputc('\n', stdout);
Life is easier if you just read the string all at once, then process the string.
char s[1000];
fgets( s, sizeof(s), stdin );
char * p = strchr( s, '\n' );
if (p) *p = '\0';
If you wanted to read one character at a time you should read once, test twice:
int c;
while ( ((c = getchar()) != '\n') and (c != EOF) )
But trying to compute the palindrome-ness at the same time as reading seriously makes your algorithm waaaaay more complicated than it needs to be. Read a string first, then compute.
Now you can use integer indices from each end of the string. If you can get them to meet (or cross) then you’ve got a palindrome. Hint: put that in a function:
bool is_palindrome( const char * s )
{
int left = 0;
int right = strlen(s) - 1;
...
}

How do I modify this program to count the number of characters that aren't spaces?

For my assignment I need to modify the following program. I can not use strings.h.
int main(void)
{
int c, countSpaces = 0;
printf("Type sentence:\n");
do
{
c = getchar();
if (c == ' ')
countSpaces = countSpaces + 1;
}
while (c != '\n');
printf("Sentence contains %d Spaces.\n", countSpaces);
return 0;
}
I tried using
if (c != EOF)
countSpaces = countSpaces + 1;
}
while (c != '\n');
printf("Sentence contains %d Spaces.\n", countSpaces - 1);
but that seems like a hacky and unelegant way to do this.
Can anyone help and/or explain to me how to do this better?
Thanks in advance
The code I posted counts the spaces in a sentence, I want to modify it to count all the characters in the input sentence. – fbN 21 secs ago
Have another counter outside the if condition.
#include <stdio.h>
int main(void)
{
int c;
int countSpaces = 0;
int countChars = 0;
puts("Type sentence:");
do {
c = getchar();
countChars += 1;
if (c == ' ') {
countSpaces += 1;
}
} while (c != '\n');
printf("Sentence contains %d spaces and %d characters.\n", countSpaces, countChars);
return 0;
}
Two notes. foo += 1 is shorthand for foo = foo + 1 without the precendence complexities of foo++.
Blockless if or while is playing with fire. Eventually you'll accidentally write this.
if( condition )
do something
whoops this is not in the condition but it sure looks like it is!
Always use the block form.
$ ./test
Type sentence:
foo bar baz
Sentence contains 2 spaces and 12 characters.
Note this says 12 because it's including the newline. That's because it's checking what c is after it's already been counted. You can fix this by checking c as its read. This is a fairly normal "read and check" C loop idiom.
// Note, the parenthesis around `c = getchar()` are important.
while( (c = getchar()) != '\n' ) {
countChars++;
if (c == ' ') {
countSpaces++;
}
}
$ ./test
Type sentence:
foo bar baz
Sentence contains 2 spaces and 11 characters.
I always prefer to use fgets() when reading a line from the console (stdin):
#include <stdio.h>
int main(void)
{
int i;
int length = 0;
char buffer[1024];
printf( "Enter some text> " );
fgets( buffer, sizeof(buffer), stdin );
// If the user inputs > 1024 letters, buffer will not be \n terminated
for ( i=0; buffer[i] != '\n' && buffer[i] != '\0'; i++ )
{
length += 1;
}
printf( "length: %d\n", length );
return 0;
}
I make this code that count length of the string given It's like strlen function.
and I used just scanf and it works perfectly even with spaces.
#include <stdio.h>
int main()
{
char *str = calloc(sizeof(char),50);
int i = 0, count = 0;
printf("Type sentence:\n");
scanf("%[^\n]",str);
while (str[i++] != '\0')
count++; //length of the string
printf("%d",count);
return 0;
}
and if you want just to count the characters in the string given use this code below:
#include <stdio.h>
int main()
{
char *str = calloc(sizeof(char),50);
int count = 0;
printf("Type sentence:\n");
scanf("%[^\n]",str);
for (int i = 0; str[i] != '\0'; i++)
if ((str[i] >= 'A' && str[i] <= 'Z') || (str[i] >= 'a' && str[i] <= 'z'))
count++;
printf("Sentence contains %d characters.\n",count);
return 0;
}
the output :
Type sentence:
hello world
Sentence contains 10 characters.
you can just calculate the result like this
int main(void)
{
int c, countSpaces = 0;
printf("Type sentence:\n");
do
{
c = getchar();
if (c == ' ')
countSpaces++;
}
while (c != '\n');
int countChar = c - countSpaces - 1 ; // -1 new line
printf("Sentence contains %d Spaces.\n", countSpaces);
printf("Sentence contains %d chars.\n", countChar);
return 0;
}

Replacing three 'a' in with a single '*' in a string

So my program should get input from an user and store it in an array. After that if the input string includes three 'a's in a row it should be replaced with a single '*'. However I can't seem to get it right. It only replaces the first a with a *. I tried to replace the following 2 a with a blank but the output looks funny.
For this exercise I have to use putchar() and getchar().
Thank you in advance.
#include <stdio.h>
char c;
char buffer[256];
int counter= 0;
int i;
int main()
{
while ((c = getchar()) != '\n') {
buffer[counter] =c;
counter++;
if (counter >255) {
break;
}
}
for(i=0; i<256; i++) {
if(buffer[i]== 'a'&&buffer[i+1]=='a'&&buffer[i+2]=='a')
{
buffer[i]= '*';
buffer[i+1]=' ';
buffer[i+2]=' ';
}
putchar(buffer[i]);
}
putchar('\n');
return 0;
}
So my program should get input from an user and store it in an array.
After that if the input string includes three 'a's in a row it should
be replaced with a single '*'. However I can't seem to get it right.
You almost got it! Just move index by 2 to and continue.
#include <stdio.h>
char c;
char buffer[256];
int counter= 0;
int i;
int main(void)
{
while ((c = getchar()) != '\n') {
buffer[counter] =c;
counter++;
if (counter >= 255) {
break;
}
}
buffer[counter] ='\0';
for(i=0; i<256; i++) {
if(buffer[i]== 'a'&&buffer[i+1]=='a'&&buffer[i+2]=='a')
{
buffer[i]= '*';
putchar(buffer[i]);
i = i + 2;
continue;
}
putchar(buffer[i]);
}
putchar('\n');
return 0;
}
Test:
123aaa456aaa78
123*456*78
In string you must assign a end of character at the end and that is call null character \0 or just a numeric 0. Correct your code like below:-
while ((c = getchar()) != '\n') {
buffer[counter] =c;
counter++;
if (counter >=255) {
break;
}
}
buffer[counter] ='\0';// or buffer[counter] =0;
To avoid side effect in a string array always set all its value with 0 first:-
char buffer[256];
memset(buffer, 0, sizeof(buffer));
If you want to change the number of characters, you will need to create a different buffer to copy the output to.
If you really just want to output to the console, you could just write every character until you hit your matching string.
#include <stdio.h>
char c;
char buffer[256];
char output[256];
int counter= 0;
int i, j;
int main()
{
while ((c = getchar()) != '\n') {
buffer[counter] = c;
counter++;
if (counter >255) {
break;
}
}
buffer[counter] = 0;
for(i=0, j=0; i<256; i++, j++) {
if(buffer[i] == 'a' && buffer[i+1] == 'a'&& buffer[i+2] == 'a')
{
output[j]= '*';
i += 2;
}
else
output[j] = buffer[i];
putchar(output[j]);
}
putchar('\n');
return 0;
}
There are multiple problems in your code:
there is no reason to make all these variables global. Declare them locally in the body of the main function.
use int for the type of c as the return value of getchar() does not fit in a char.
you do not check for EOF.
your test for buffer overflow is off by one.
you do not null terminate the string in buffer. You probably make buffer global so it is initialized to all bits 0, but a better solution is to set the null terminator explicitly after the reading loop.
to replace a sequence of 3 characters with a single one, you need to copy the rest of the string.
You can use a simple method referred as the 2 finger approach: you use 2 different index variables into the same array, one for reading, one for writing.
Here is how it works:
#include <stdio.h>
int main() {
char buffer[256];
int c;
size_t i, j, counter;
for (counter = 0; counter < sizeof(buffer) - 1; counter++) {
if ((c = getchar()) == EOF || c == '\n')
break;
buffer[counter] = c;
}
buffer[counter] = '\0';
for (i = j = 0; i < counter; i++, j++) {
if (buffer[i] == 'a' && buffer[i + 1] == 'a' && buffer[i + 2] == 'a') {
buffer[j] = '*';
i += 2;
} else {
buffer[j] = buffer[i];
}
}
buffer[j] = '\0'; /* set the null terminator, the string may be shorter */
printf("modified string: %s\n", buffer);
return 0;
}

How to store array in address C

basically we are provided with the main function:
#include <stdio.h>
#include <string.h>
#include <strings.h>
#define STORAGE 255
{
int c;
char s[STORAGE];
for(;;) {
(void) printf("n=%d, s=[%s]\n", c = getword(s), s);
if (c == -1)break;
}}
we are not to change that
and we have to create the function getword() which should contain a loop that reads a characters,
store it in a array in the address provided one by one and it should stop for whitespace (tab, space, eof)
basically i have this:
int getword(char *w)
{
char str[255];
int i = 0;
int charCount = 0;
printf("enter your sentence:\n");
gets(str);
/*this was provided by the professor, but i'm not sure how to use it
while (( iochar - getchar()) !=EOF);
*/
for(i = 0; str[i] != '\0'; i++) //loop that checks tab and spaces
{
if(str[i] != ' ' && str[i] != '\t')
{
charCount++;
}
}
printf("your string: '%s' contains %d of letters\n", str, charCount);
return 0;}
right now the output of the program is:
enter your sentence:
hey stockoverflow
your string: 'hey stockoverflow' contains 16 of letters
n=0, s=[]
so i'm saving the string and counting it, but i'm not storing it where i should be.
it should display n=16, s=[hey stockoverflow]
actually it should display n=3, s=[hey]
any help would be appreciated
This may be what you are looking for:
for(i = 0; str[i] != '\0'; i++) //loop that checks tab and spaces
{
if(str[i] != ' ' && str[i] != '\t')
{
charCount++;
}
else
{
str[i] = '\0'; // Terminate str
break; // Break out of the for-loop
}
}
printf("your string: '%s' contains %d of letters\n", str, charCount);
strcpy(w, str); // Add this line to copy str into w (which is s from main)
return strlen(w); // Return the length of the result string

Resources