Program compiles, but when I try to use it, I get an endless loop. Where did i do wrong. I put comments into what I am trying to accomplish.
I have tried changing it to a for loop, but I still get issues. I think I am suppose to stick with a while loop to accomplish what I am trying to accomplish.
//Declare the arrays to hold the strings
char str[21], vowels[21], consonants[21];
int i=0;
//Declare the pointers
char *strPointer, *vowelPointer, *consonantPointer;
//Print out the prompt to the user
printf("Enter a string (20 characters maximum): ");
//Scan the user input into str
//Only allow 20 characters
scanf("%s", str);
//Set strPointer to the beginning of the user's string
strPointer = str;
//Set vowelPointer to the beginning of the vowels string
vowelPointer = vowels;
//Set consonantPointer to the beginning of tht consonant string
consonantPointer = consonants;
//Loop through the user's string until the end of the string
while(*strPointer !='\0')
{
//Check if what strPointer is pointing to is a vowel
if(strPointer[i]=='A'||strPointer[i]=='a'||strPointer[i]=='E'||strPointer[i]=='e'||strPointer[i]=='I'||strPointer[i]=='i'||strPointer[i]=='O'||strPointer[i]=='o'||strPointer[i]=='U'||strPointer[i]=='u')
{
//Move the letter from strPointer to vowelPointer
strPointer=vowelPointer
;
//Move the vowelPointer
vowelPointer=vowels
;
}
else
{
//Move the letter from strPointer to consonantPointer
strPointer=consonantPointer
;
//Move the consonantPointer
consonantPointer=consonants
;
}
//Move the strPointer
strPointer=str;
}
//Add null terminators where appropriate
strPointer[21]='\0';
str[21]='\0';
//Set the vowel and consonant pointers back to the beginning of their strings
vowelPointer[0];
consonantPointer[0];
//Print the original string and the resulting vowel and consonant strings
printf("Original string: %s\n", str);
printf("%s\n", vowelPointer);
printf("%s\n", consonantPointer);
The output is explained in my printf statements at the end. Input string, reprinted with the vowels and consonants separated and listed.
I would like to make some suggestions to help you out.
First, when you are scanning from user input, it is wise to use a buffer. Then, strcpy the contents of the buffer into the char array. This will help to prevent overflow. Please see the below code for more details about this topic.
Second, you can use a for loop to iterate through each of the letters. I hope my answer will help you understand what I mean.
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int main(void)
{
//Declare the arrays to hold the strings
char c, str[21], vowels[21], consonants[21], buffer[21];
int i = 0, j = 0, h = 0;
//Declare the pointers
char *strPointer, *vowelPointer, *consonantPointer;
//Print out the prompt to the user
printf("Enter a string (20 characters maximum): ");
//Scan the user input into str
scanf("%s", buffer);
// Copy the buffer into the str
strcpy(str, buffer);
// go letter by letter checking if it is a vowel or consonant
for (int i = 0; str[i]; i++)
{
// make the character uppercase
c = toupper(str[i]);
// if the letter is a vowel add the letter to the vowel array,
// then increase the position
if (c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U')
vowels[j++] = str[i];
else
// add the letter to the consonants array, then increase the position
consonants[h++] = str[i];
}
// properly terminate the strings
vowels[j] = '\0';
consonants[h] = '\0';
//Print the original string and the resulting vowel and consonant strings
printf("Original string: %s\n", str);
printf("%s\n", vowels);
printf("%s\n", consonants);
return 0;
}
You invoke an infinite loop by setting:
strPointer=str;
at the end of your while (*strPointer !='\0') loop. This resets the address held by strPointer to the beginning of str. strPointer is never incremented, so your loop loops with strPointer pointing to the first character in str over-and-over-and-over again...
Further, you initialize vowelPointer=vowels; which sets the address of vowelPointer to point to the beginning element of the uninitialized vowels array. The same occurs with consonantPointer=consonants;
Since both vowelPointer and consonantPointer point to arrays declared with automatic storage duration, you invoke Undefined Behavior when you attempt to access the uninitialized values with:
printf("%s\n", vowelPointer);
printf("%s\n", consonantPointer);
(but luckily you never get there because of your endlesss loop over while (*strPointer !='\0'))
Additionally, validate EVERY input and affirmatively protect your array bounds by using the field-width modifier with scanf (or better, use fgets()). For example:
//Only allow 20 characters
if (scanf( "%20s", str) != 1) {
fputs ("error: (user canceled input)\n", stderr);
return 1;
}
(note: when reading with "%s" the trailing '\n' is not consumed and will remain in your input buffer)
To fix your pointer problems, you can do something similar to the following:
//Declare the arrays to hold the strings
char str[21], vowels[21], consonants[21];
size_t vidx = 0, cidx = 0; /* indexes for vowels/consonants */
...
//Loop through the user's string until the end of the string
while (*strPointer)
{
//Check if what strPointer is pointing to is a vowel
if (strPointer[i]=='A'|| strPointer[i]=='a'||
strPointer[i]=='E'|| strPointer[i]=='e'||
strPointer[i]=='I'|| strPointer[i]=='i'||
strPointer[i]=='O'|| strPointer[i]=='o'||
strPointer[i]=='U'|| strPointer[i]=='u')
{
//Copy the letter from strPointer to vowelPointer
if (vidx < 20) {
vowelPointer[vidx] = *strPointer;
vidx++;
}
/* or using pointer arithmetic */
// if (vowelPointer - vowels < 20) {
// *vowelPointer = *strPointer;
// vowelPointer++;
// }
}
else {
//Copy the letter from strPointer to consonantPointer
if (cidx < 20) {
consonantPointer[cidx] = *strPointer;
cidx++;
}
/* same alternative available for consonantPointer */
}
//Move the strPointer
strPointer++;
}
//Add null terminators where appropriate
vowelPointer[vidx] = 0;
consonantPointer[cidx] = 0;
//Reset the ponters
vowelPointer = vowels;
consonantPointer = consonants;
//Print the original string and the resulting vowel and consonant strings
printf("Original string: %s\n", str);
printf("%s\n", vowelPointer);
printf("%s\n", consonantPointer);
If you are still stuck, you can put it altogether in a short, slightly more concise example as:
#include <stdio.h>
#include <ctype.h>
#define MAXC 1024 /* don't skimp on buffer size */
int main (void) {
char str[MAXC], cons[MAXC], vowels[MAXC], /* arrays */
*strptr = str, *consptr = cons, *vowelptr = vowels; /* pointers */
fputs ("Enter a string (1022 characters maximum): ", stdout);
if (!fgets (str, MAXC, stdin)) { /* validate EVERY read */
fputs ("error: (user canceled input)\n", stderr);
return 1;
}
while (*strptr) { /* loop over each character */
char lc = tolower (*strptr); /* convert to lowercase to compare */
if (lc == 'a' || lc == 'e' || lc == 'i' || lc == 'o' || lc == 'u')
*vowelptr++ = *strptr; /* copy vowel to array */
else if (!isspace (*strptr)) /* otherwise if not whitespace */
*consptr++ = *strptr; /* copy to consonant array */
strptr++; /* advance string pointer */
}
*vowelptr = *consptr = 0; /* nul-terminate arrays */
printf ("str : %scons : %s\nvowels: %s\n", str, cons, vowels);
}
(question: do you know why there is no '\n' needed after "str : %s" in the printf above?)
Note above that the character is converted to lowercase before comparison for a vowel to cut in-half the number of conditionals needed to check for a vowel. Don't skimp on buffer size. Generally you have 1M of stack space (4M on Linux). Use a buffer of at least 256-chars, or a simple 1K buffer as used above. Also note if you wanted to print using the pointer, you would simply reset them to point to the original arrays immediately after exiting the loop, e.g.
strptr = str;
consptr = cons;
vowelptr = vowels;
Regardless, you can print using the arrays or the pointers after resetting them as both will both point to the same address. See C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3)
Example Use/Output
$ ./bin/sepvowels
Enter a string (1022 char max): A quick brown fox jumps over the lazy dog
str : A quick brown fox jumps over the lazy dog
cons : qckbrwnfxjmpsvrthlzydg
vowels: Auioouoeeao
Related
Whenever a word from wordlist passes as a valid word, strcat(code,wordlist[i]) is called to add the word to world list.
So if at the first line "am" is put, code=am.
Or if abhcgmsopa bqcedpwon abmnpc abcdponm dfajbbmmn cabnmo is put at the first line, the three corresponding valid words are put.
However at the second line the values in code get overwritten and extra characters are put, even though code is initialized outside the while-loop and strcat should append the values to the end of code. Then when the while-loop ends, code is replaced by the entirely by "xq", where x was the first letter put into code and q is from "quitting".
Code isn't reinitialized or changed aside from what is appended to it.
How can I prevent this?
Thanks
*Edit: I defined some stack functions before the main but edited it out here to minimize the code
int main(int argc, char const *argv[])
{
char input[300];
char code[]="";
int ci;
/* set up an infinite loop */
while (1)
{
//break;
/* get line of input from standard input */
printf ("\nEnter input to check or q to quit\n");
fgets(input, 300, stdin);
/* remove the newline character from the input */
int i = 0;
while (input[i] != '\n' && input[i] != '\0')
{
i++;
}
input[i] = '\0';
/* check if user enter q or Q to quit program */
if ( (strcmp (input, "q") == 0) || (strcmp (input, "Q") == 0) )
break;
/*Start tokenizing the input into words separated by space
We use strtok() function from string.h*/
/*The tokenized words are added to an array of words*/
char delim[] = " ";
char *ptr = strtok(input, delim);
int j = 0 ;
char *wordlist[300];
while (ptr != NULL)
{
wordlist[j++] = ptr;
ptr = strtok(NULL, delim);
}
/*Run the algorithm to decode the message*/
//j=words in line;i=i-th word we are evaluating
//k=k-th letter in i-th word
stack1 st;
for(int i=0;i<j;i++){
//stack1 st;
init(&st);
for(int k=0;k<strlen(wordlist[i]);k++){
if((int)wordlist[i][k]<101 && (int)wordlist[i][k]>96){ //check if this letter is a/b/c/d with ascii
push(&st,&wordlist[i][k]);
printf("%c added\n",st.ptr[st.inUse-1]);
}
else{
if(wordlist[i][k]==top(&st)+12){ //check if letter is m/n/o/p corresponding to a/b/c/d from top()
pop(&st);
}
}
}
if(is_empty(&st)){
printf("%s is valid\n",wordlist[i]);
strcat(code,wordlist[i]);
strcat(code," ");
}
else{
printf("%s is invalid\n",wordlist[i]);
clear(&st);
}
printf("code:%s\n",code);
}
printf("code after loop: %s",code);
}
printf("code: %s\n",code);
for(int i=0;i<300;i++){
if ((int)code[i]<101 && (int)code[i]>96){
printf("%c",code[i]);
}
if(!((int)code[i]<96+26 && (int)code[i]>96)){
printf(" ");
}
}
printf("code:%s",code);
printf ("\nGoodbye\n");
return 0;
}
The problem is that your code variable is an array of 1 character! This line:
char code[]="";
declares it as an empty string (no characters) plus a null terminator.
You need to assign it as an array big enough to hold the maximum possible answer! If this is, say, 500, then use this:
char code[500]="";
I am trying to delete the blank space between a string and print out the first word with isalpha() function.
When I print out, only the first letter prints out. exempel "hello big panda" I get "hhhhh" but I want the hole word "hello" instead
int main()
{
char inputString[]={"hello big panda"};
int k=0;
int i=0;
do
{
inputString[i];
i++;
}
while (inputString[i]=isalpha(inputString[i]));
for(i=0; inputString[i] !='\0' ;i++)
{
for (k=i; inputString[k] != '\0'; k++)
{
inputString[k] =inputString[i];
}
}
printf("%s", inputString);
return 0;
}
done this:
int printfirstword(char sentence[])
{
int k=0;
int i=0;
while (isalpha(sentence[i])) //checking for the first blank space
{
i++;
}
sentence[i] = '\0';
printf("%s\n", sentence);
return 0;
}
int main()
{
char sentence[100];
int wordNumber;
char answer;
printfirstword("Hello there")
return0;
}
But I don't want to change the string that is passed to it
What you can simply do is use a while loop instead of your do-while. You can simply increment i until you find the index of first blank space. Then using the value of i you can insert '\0' in your string. Output it and you are done. :)
#include <stdio.h>
#include<ctype.h>
int main()
{
char inputString[]={"hello big panda"};
int k=0;
int i=0;
while (isalpha(inputString[i])) //checking for the first blank space
{
i++;
}
inputString[i] = '\0';
printf("%s", inputString);
return 0;
}
If you would like to keep the original string then you could simply make a new string say newStr and then
while (isalpha(inputString[i])) //checking for the first blank space
{ newStr[i]=inputString[i]; //copy first word into newStr
i++;
}
newStr[i] = '\0';
printf("%s", newStr);
Your function must do 3 things as it works through the sentence finding words. (1) always check for the end of the string to prevent an attempted read beyond the end of the sentence; and (2) locate and print the requested word at the index given; and (3) handle the condition where the user requests a word index greater than that available.
(you should always test the sentence you are passed in the function to make sure the pointer isn't a NULL pointer, and that the contents of the sentence is simply the '\0' character indicating an empty-string)
An easy way to do this (after you have tested the input string), is to set up a continual loop, that repeatedly read the characters of a word, checks if it is the word to print (if so it prints), and if not read and discard all the non-alpha characters before the next word, and then repeats.
Something simple like the following works. It takes the sentence (or updated position within the sentence) and the index for the word to print zero-indexed, e.g. (0, 1, 2, ...) and then loops a described above.
(note: you can change the zero-index scheme to a 1, 2, 3, ... word-number scheme by initializing n=1; instead of 0 -- but since everything in C is zero indexed, that is left to you)
#include <stdio.h>
#include <ctype.h>
int prnword (const char *s, int nwrd)
{
int n = 0; /* word counter */
char *p = s; /* pointer to s */
if (!s || !*s) { /* test s not NULL and not empty */
fprintf (stderr, "error: string NULL, empty or at end.\n");
return 0;
}
for (;;) { /* loop continually until exit condition reached */
while (*p && isalpha(*p)) { /* loop over chars in s */
if (n == nwrd) /* if requested index */
putchar (*p); /* print all chars */
p++; /* increment pointer */
}
while (*p && !isalpha(*p)) /* iterate find next alpha */
p++;
if (++n > nwrd) /* if past our word, break */
break;
if (!*p) /* if end reached, break */
break;
}
if (n <= nwrd) { /* check request exceeds avaialble words */
fprintf (stderr, "error: request word '%d' "
"exceeds available wprds indexes.\n", nwrd);
return 0;
}
putchar ('\n'); /* tidy up with new line */
return p - s; /* return number of chars to next alpha */
}
int main (void) {
char str[] = "hello big panda";
int nchars = 0;
/* example -- all words in order
* passing update string position
*/
nchars = prnword (str, 0);
nchars += prnword (str + nchars, 0);
nchars += prnword (str + nchars, 0);
putchar ('\n');
/* request exceed available zero-based word indexes */
nchars = 0;
nchars += prnword (str, 3);
putchar ('\n');
/* print 2nd word only */
nchars = 0;
nchars = prnword (str, 1);
putchar ('\n');
return 0;
}
Example Use/Output
Note the first block of calls to prnword print each of the words in the sentence, saving the number of characters returned by prior calls and using that to start the function reading the 1st character of the desired word, meaning you are always looking for word index 0.
The second call intentionally gives an index one past the last word to force handling the error.
And finally, the last call simply says "Go print word 2" (index 1) starting from scratch.
Example Use/Output
$ ./bin/words
hello
big
panda
error: request word '3' exceeds available wprds indexes.
big
Look things over and let me know if you have questions.
My program tokenizes a string of input from the user, and from those tokens, discern whether or not they are a string or int(if any alphabetical character is attached to a number, meaning it is adjacent to any number - it is then treated as a string).
Hence, the following input: "this is 1string 123 1", should output STR STR STR INT INT. What I did: take the input string, proceed to tokenize/split it(with a space delimiter), and then iterate through the split token(using a for loop) to see whether or not the split token, has any character from the alphabet(upper-case or lower-case).
Now, that last sentence is the problem. I have a boolean called foundChar. If any alphabetical characters were found, then I would set foundChar to true. From there, I would do a simple if check to see if foundChar == true. However, now when I input a string, it prints blanks? I'm not sure if the way I'm using booleans is correct in C, or where to exactly pinpoint what is going wrong here.
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
// main
int main (void)
{
// declare our stuff for stuffs
char string[255];
char *tokenizedString;
const char delimiter[2] = " ";
char *pch;
bool found = false;
int truth = 0;
// prompt our user
do {
do {
printf (">");
fgets (string, 65, stdin);
} while (strlen (string) <= 0);
// remove it "\n" so it can terminate from newline input
pch = strstr (string, "\n");
strncpy (pch, "\0", 1);
// tokenize the input string
tokenizedString = strtok (string, delimiter);
while (tokenizedString != NULL) {
// check for any character in the token
// if found = true, then it's a string by our premade definition
for (int i = 0; i < strlen (tokenizedString); i++) {
if ((i >= 'a' && i <= 'z')
|| (i >= 'A' && i <= 'Z')) {
found = true;
}
}
// if we find a char in the string
if (found == true) {
printf ("STR ");
}
// if the token is a number
else if (isdigit (*tokenizedString))
printf ("INT ");
tokenizedString = strtok (NULL, delimiter);
// reset charFound to zero for our next token
found = false;
}
printf ("\n");
} while (!(strlen (string) == 0));
} // end of program
OUTPUT
./prog why are
_________(nothing actually prints here, blank! STR STR should print, same for the next string below!)
./prog you not printing output for string
_________(nothing prints here as well, should print STR STR STR STR STR STR)
./prog 123
INT
./prog 1st
INT
./prog nor printing the right stuff
DESIRED OUTPUT
./prog why are
STR STR
./prog you not printing output for string
STR STR STR STR STR STR
./prog 123
INT
./prog 1st
STR
./prog nor printing the right stuff
STR STR STR STR STR
Since BLUEPIXY has correctly pointed out (as usual) the need to check whether the character in the tokenizedString is a digit or char, let's step back a bit and look at what you are doing from the big picture. While there is nothing wrong with tokenizing each string read and then iterating over each character in each token -- there is also no need for it.
All you really care about is whether each word in the line is made up solely of digits (for your INT output), otherwise you classify it as a STR. To do so, all you need to do is iterate over each character in your input and count the number of characters and digits between the spaces contained in the line. You can do so without any tokenization. Just keep count of the number of characters and number of digits encountered between each space you find (or those between the last space and the '\n' included in your input by fgets).
For example, you can do something like the following:
#include <stdio.h>
#define MAXS 256
int main (void) {
char str[MAXS] = "";
while (fgets (str, MAXS, stdin)) { /* read each line */
char *p = str;
int ch = 0, dig = 0;
while (*p) { /* for each char */
if (*p == ' ' || *p == '\n') { /* if space or \n */
if (ch) /* if char found */
printf (" STR");
else if (dig) /* if digit found */
printf (" INT");
}
/* are we a char? */
if (('a' <= *p && *p <= 'z') || ('A' <= *p && *p <= 'Z'))
ch++; /* incriment ch */
else if ('0' <= *p && *p <= '9') /* are we a digit? */
dig++; /* incriment dig */
p++;
}
putchar ('\n');
}
return 0;
}
Example Use/Output
$ ./bin/str_or_int
why are
STR STR
you not printing output for string
STR STR STR STR STR STR
123
INT
1st
STR
nor printing the right stuff
STR STR STR STR STR
Again, there is nothing wrong with tokenizing and then scanning each token, but it may be a bit more complicated than it need be. Look things over, incorporate the fix suggested by BLUEPIXY in your code, and compare the versions. Generally if there is a simple way to do something, you have a lot less chance of stumbling into a subtle error than you do if you take the long way around :)
Let me know if you have any further questions on either version.
I tried to get the inputs(strings) from user and store them in an array.But after I ran this code, the program instantly crashed.
#include <stdio.h>
int main() {
int i;
char *word[3];
for(i=0;i<3;i++)
{
printf(" Enter a word: ");
scanf("%s", &word[i]);
}
printf("%s ", word[0]);
return 0;
}
In this line:
scanf("%s", &word[i]);
You need to make sure word[i] is pointing somewhere, and has enough space to occupy the string entered. Since word[i] is a char * pointer, you need to at some time allocate memory for this. Otherwise, it is just a dangling pointer not pointing anywhere.
If you want to stick with scanf(), then you can allocate some space beforehand with malloc.
malloc() allocates requested memory on the heap, then returns a void* pointer at the end.
You can apply malloc() in your code like this:
size_t malloc_size = 100;
for (i = 0; i < 3; i++) {
word[i] = malloc(malloc_size * sizeof(char)); /* allocates 100 bytes */
printf("Enter word: ");
scanf("%99s", word[i]); /* Use %99s to avoid overflow */
/* No need to include & address, since word[i] is already a char* pointer */
}
Note: Must check return value of malloc(), because it can return NULL when unsuccessful.
Additionally, whenever you allocate memory with the use of malloc(), you must use free to deallocate requested memory at the end:
free(word[i]);
word[i] = NULL; /* safe to make sure pointer is no longer pointing anywhere */
Another approach without scanf
A more proper way to read strings should be with fgets.
char *fgets(char *str, int n, FILE *stream) reads a line from an input stream, and copies the bytes over to char *str, which must be given a size of n bytes as a threshold of space it can occupy.
Things to note about fgets:
Appends \n character at the end of buffer. Can be removed easily.
On error, returns NULL. If no characters are read, still returns NULL at the end.
Buffer must be statically declared with a given size n.
Reads specified stream. Either from stdin or FILE *.
Here is an example of how it can be used to read a line of input from stdin:
char buffer[100]; /* statically declared buffer */
printf("Enter a string: ");
fgets(buffer, 100, stdin); /* read line of input into buffer. Needs error checking */
Example code with comments:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NUMSTR 3
#define BUFFSIZE 100
int main(void) {
char *words[NUMSTR];
char buffer[BUFFSIZE];
size_t i, count = 0, slen; /* can replace size_t with int if you prefer */
/* loops only for three input strings */
for (i = 0; i < NUMSTR; i++) {
/* read input of one string, with error checking */
printf("Enter a word: ");
if (fgets(buffer, BUFFSIZE, stdin) == NULL) {
fprintf(stderr, "Error reading string into buffer.\n");
exit(EXIT_FAILURE);
}
/* removing newline from buffer, along with checking for overflow from buffer */
slen = strlen(buffer);
if (slen > 0) {
if (buffer[slen-1] == '\n') {
buffer[slen-1] = '\0';
} else {
printf("Exceeded buffer length of %d.\n", BUFFSIZE);
exit(EXIT_FAILURE);
}
}
/* checking if nothing was entered */
if (!*buffer) {
printf("No string entered.\n");
exit(EXIT_FAILURE);
}
/* allocate space for `words[i]` and null terminator */
words[count] = malloc(strlen(buffer)+1);
/* checking return of malloc, very good to do this */
if (!words[count]) {
printf("Cannot allocate memory for string.\n");
exit(EXIT_FAILURE);
}
/* if everything is fine, copy over into your array of pointers */
strcpy(words[count], buffer);
/* increment count, ready for next space in array */
count++;
}
/* reading input is finished, now time to print and free the strings */
printf("\nYour strings:\n");
for (i = 0; i < count; i++) {
printf("words[%zu] = %s\n", i, words[i]);
free(words[i]);
words[i] = NULL;
}
return 0;
}
Example input:
Enter a word: Hello
Enter a word: World
Enter a word: Woohoo
Output:
Your strings:
words[0] = Hello
words[1] = World
words[2] = Woohoo
There seems to be a bit of confusion in this area. Your primary problem is you are attempting to write each word to the address of each of pointers you declare with char *word[3];. (not to mention you have no storage allocated at the location pointed to by each pointer -- but you never get there as you attempt to write to the address of each pointer with &word[i] rather than to the pointer itself)
While you can use scanf you will quickly run into one of the many pitfalls with taking user input with scanf that plague all new C programmers (e.g. failing to handle the '\n' left in the input buffer, failing to handle whitespace in strings, failing to limit the number of characters read/written, failing to validate the read or handle EOF, etc...)
A better approach is to simply use fgets and then trim the '\n' that fgets read and includes in the buffer to which it stores the string. A simple example would be:
#include <stdio.h>
#include <string.h>
#define NWDS 3 /* declare a constant for the maximum number of words */
int main (void) {
int i, n = 0;
char word[NWDS][50] = { "" }; /* provide storage or allocate */
for (i = 0; i < NWDS; i++) { /* for a max of NWDS */
printf ("Enter word : "); /* prompt */
if (!fgets (word[i], sizeof word[i], stdin)) /* read/validate */
break; /* protect against EOF */
size_t len = strlen (word[i]); /* get length */
if (word[i][len-1] == '\n') /* check for trailing '\n' */
word[i][--len] = 0; /* overwrite with nulbyte */
}
n = i; /* store number of words read */
putchar ('\n'); /* make it pretty */
for (i = 0; i < n; i++) /* output each word read */
printf (" word[%d] : %s\n", i, word[i]);
#if (defined _WIN32 || defined _WIN64)
getchar(); /* keep terminal open until keypress if on windows */
#endif
return 0;
}
Go ahead and cancel input at any time by generating an EOF during input (ctrl + d on Linux or ctrl + z on windoze), you are covered.
Example Use/Output
$ ./bin/wordsread
Enter word : first word
Enter word : next word
Enter word : last word
word[0] : first word
word[1] : next word
word[2] : last word
Looks things over, consider the other answers, and let me know if you have further questions.
char *word[3]; // <-- this is an array of 3 dangling pointers, of type char*
// they still point nowhere, we later need to set them to some allocated location.
...
for(i=0;i<3;i++) {
word[i] = malloc(some_max_size * sizeof(char)); // <-- allocate space for your word
printf(" Enter a word: ");
scanf("%s", word[i]); // <-- not &word[i]; word[i] is already a char* pointer
}
You are declaring word as array of pointer (char *word[3];). You have to allocate memory to store data. Allocate memory with malloc or similar functions before assigning values.
Yes the code crashes because declaring an array of character
pointers is not enough, you need to set the pointers to point
to memory where the strings can be stored.
E.g.
const int maxLen = 32;
char* word[3] = {NULL,NULL,NULL};
word[i] = malloc(maxLen);
then read the string from keyboard, to ensure that the string is not too
long use fgets and maxLen:
printf("Enter a word:");
fgets(word[i],maxLen,stdin);
#include <stdio.h>
int main(){
int n;
int i=0;
scanf("%d",&n);
char arr[n];
while(n>i){
scanf("%s",&arr[i]);
i+=1;
}
while(n-i<n){
printf(" %c ",arr[n-i]);
i-=1;
}
}
The code char *word[3] made a 3-element array of pointers!
See, you have basically created a character array of pointers, so you cannot put a "string" into each one of them, because the type of a pointer variable is long hexadecimal.
I am trying to write a program that reads the stdin stream looking for words (consecutive alphabetic characters) and for each word rotates it left to the first vowel (e.g. "friend" rotates to "iendfr") and writes this sequence out in place of the original word. All other characters are written to stdout unchanged.
So far, I have managed to reverse the letters, but have been unable to do much more. Any suggestions?
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#define MAX_STK_SIZE 256
char stk[MAX_STK_SIZE];
int tos = 0; // next available place to put char
void push(int c) {
if (tos >= MAX_STK_SIZE) return;
stk[tos++] = c;
}
void putStk() {
while (tos >= 0) {
putchar(stk[--tos]);
}
}
int main (int charc, char * argv[]) {
int c;
do {
c = getchar();
if (isalpha(c) && (c == 'a' || c == 'A' || c == 'e' || c == 'E' || c == 'i' || c == 'o' || c == 'O' || c == 'u' || c == 'U')) {
push(c);
} else if (isalpha(c)) {
push(c);
} else {
putStk();
putchar(c);
}
} while (c != EOF);
}
-Soul
I am not going to write the whole program for you, but this example shows how to rotate a word from the first vowel (if any). The function strcspn returns the index of the first character matching any in the set passed, or the length of the string if no matches are found.
#include <stdio.h>
#include <string.h>
void vowelword(const char *word)
{
size_t len = strlen(word);
size_t index = strcspn(word, "aeiou");
size_t i;
for(i = 0; i < len; i++) {
printf("%c", word[(index + i) % len]);
}
printf("\n");
}
int main(void)
{
vowelword("friend");
vowelword("vwxyz");
vowelword("aeiou");
return 0;
}
Program output:
iendfr
vwxyz
aeiou
There are a number of ways your can approach the problem. You can use a stack, but that just adds handling the additional stack operations. You can use a mathematical reindexing, or you can use a copy and fill solution where you copy from the first vowel to a new string and then simply add the initial characters to the end of the string.
While you can read/write a character at a time, you are probably better served by creating the rotated string in a buffer to allow use of the string within your code. Regardless which method you use, you need to validate all string operations to prevent reading/writing beyond the end of your input and/or rotated strings. An example of a copy/fill approach to rotating to the first vowel in your input could be something like the following:
/* rotate 's' from first vowel with results to 'rs'.
* if 's' contains a vowel, 'rs' contains the rotated string,
* otherwise, 'rs' contais 's'. a pointer to 'rs' is returned
* on success, NULL otherwise and 'rs' is an empty-string.
*/
char *rot2vowel (char *rs, const char *s, size_t max)
{
if (!rs || !s || !max) /* validate params */
return NULL;
char *p = strpbrk (s, "aeiou");
size_t i, idx, len = strlen (s);
if (len > max - 1) { /* validate length */
fprintf (stderr, "error: insuffieient storage (len > max - 1).\n");
return NULL;
}
if (!p) { /* if no vowel, copy s to rs, return rs */
strcpy (rs, s);
return rs;
}
idx = p - s; /* set index offset */
strcpy (rs, p); /* copy from 1st vowel */
for (i = 0; i < idx; i++) /* rotate beginning to end */
rs[i+len-idx] = s[i];
rs[len] = 0; /* nul-terminate */
return rs;
}
Above, strpbrk is used to return a pointer to the first occurrence of a vowel in string 's'. The function takes as parameters a pointer to a adequately sized string to hold the rotated string 'rs', the input string 's' and the allocated size of 'rs' in 'max'. The parameters are validated and s is checked for a vowel with strpbrk which returns a pointer to the first vowel in s (if it exists), NULL otherwise. The length is checked against max to insure adequate storage.
If no vowels are present, s is copied to rs and a pointer to rs returned, otherwise the pointer difference is used to set the offset index to the first vowel, the segment of the string from the first vowel-to-end is copied to rs and then the preceding characters are copied to the end of rs with the loop. rs is nul-terminated and a pointer is returned.
While I rarely recommend the use of scanf for input, (a fgets followed by sscanf or strtok is preferable), for purposes of a short example, it can be used to read individual strings from stdin. Note: responding to upper/lower case vowels is left to you. A short example setting the max word size to 32-chars (31-chars + the nul-terminating char) will work for all known words in the unabridged dictionary (longest word is 28-chars):
#include <stdio.h>
#include <string.h>
enum { BUFSZ = 32 };
char *rot2vowel (char *rs, const char *s, size_t max);
int main (void)
{
char str[BUFSZ] = {0};
char rstr[BUFSZ] = {0};
while (scanf ("%s", str) == 1)
printf (" %-8s => %s\n", str, rot2vowel (rstr, str, sizeof rstr));
return 0;
}
Example Use/Output
(shamelessly borrowing the example strings from WeatherVane :)
$ echo "friend vwxyz aeiou" | ./bin/str_rot2vowel
friend => iendfr
vwxyz => vwxyz
aeiou => aeiou
Look it over and let me know if you have any questions. Note: you can call the rot2vowel function prior to the printf statement and print the results with rstr, but since the function returns a pointer to the string, it can be used directly in the printf statement. How you use it is up to you.