I cant get the right output and I wonder where my mistake is. Probably there are mistakes in loops in the counting reverse. The main problem in my whole code is that it only outputs marks but not words. Also the program must end automatically when putting these three punctuation and shows the output.
This is the expected behavior:
Input: my name is jake.//terminates when putting . and automatically shows the output
Output: jake is name my.
Here is the program fragment of my first loop:
#include <stdio.h>
#define N 70
int main(void) {
char array[N] = { 0 };
char *p;
char mark = 0;
int c;
p = array;
scanf("%d", &c);
while ((c = getchar()) != '\n') {
if (p < array + N) {
if (c == '.' || c == '!' || c == '?')
mark = c;
if (c == ' ') {
*p = '\0';
*p++;
} else
*p = c;
}
}
*p = '\0';
while (--p > array) {
if (p[1])
printf("%s", p + 1);
}
printf("%s", array);
if (mark)
printf("%c", mark);
}
Your code with little modifications:
#include <stdio.h>
#define N 70
int main (void) {
char array[N+1] = { 0 };
char* p;
char mark = 0;
int c;
p = array;
//scanf ("%d", &c); //serves no purpose : are you reading sentence length here?
while ( (c = getchar()) != '\n') {
if (p < array + N) {
if (c == '.' || c == '!' || c == '?') {
mark = c;
*p++ = '\0';
break; // stop reading input
} else if (c == ' ') {
*p++ = '\0';
} else
*p++ = c;
}
}
*p = '\0';
while (--p > array) {
if ('\0' == *p && '\0' != *(p + 1))
printf ("%s ", p + 1);
}
printf ("%s", array);
if (mark)
printf ("%c", mark);
return 0;
}
There is a better way, but that will make use of string library functions.
Here is an alternative where the original string is not modified:
#include <stdio.h>
#include <string.h>
void print_swap(const char *s) {
int p1, p2, tail = strcspn(s, ".!?\n");
for (p1 = p2 = tail; p1 > 0; p1--) {
if (s[p1 - 1] == ' ') {
printf("%.*s ", p2 - p1, s + p1);
p2 = p1 - 1;
}
}
printf("%.*s%s", p2, s, s + tail);
}
int main() {
char array[80];
if (fgets(array, sizeof array, stdin))
print_swap(array);
return 0;
}
Related
I am trying to make a program that would take a sentence from the user and reverse the order of the words while keeping the special characters ['.','?','!'] at the end.
the problem I'm getting is that I get weird symbols after the last word and the special character.
I am programming using C.
I think it's because the last element printed is not a '\0'.
but I don't know how to fix that.
My code:
#include <ctype.h>
#define N 200
int main()
{
char arr[N] = { 0 };
char* p, * q, mark = 0;
int c;
p = arr;
printf("Enter a sentence: ");
while ((c = getchar()) != '\n' && p < arr + N)
{
if (c == '?' || c == '.' || c == '!')
{
mark = c;
break;
}
else
*p++ = c;
}
*p = '\0';
printf("Reversal of sentence: ");
while (p >= arr)
{
while (*--p != ' ' && p != arr);
if (p == arr) {q = arr;}
else {q = p + 1;}
while (*q != '\0' && *q != ' ')
{
printf("%c", *q++);
}
if (p >= arr)
{
printf(" ");
}
}
printf("%c", mark);
printf("\n");
return 0;
}
I've fixed the overflow error when reading the sentence by removing the \0 termination. The input string is never used by anything that cares. I've also added a check for End-Of-File.
Next I changed the reversal loop to not underflow and fixed outputing an extra ' ' before the mark.
Last the printf calls can use putchar instead.
#include <ctype.h>
#include <stdio.h>
#define N 200
int main()
{
char arr[N] = { 0 }; // initialization optional, nothing cares
char* p, * q, mark = 0;
int c;
p = arr;
printf("Enter a sentence: ");
while ((c = getchar()) != '\n' && c != EOF && p < arr + N)
{
if (c == '?' || c == '.' || c == '!')
{
mark = c;
break;
}
else
*p++ = c;
}
printf("Reversal of sentence: ");
while (p > arr)
{
while (*--p != ' ' && p != arr);
if (p == arr) {q = arr;}
else {q = p + 1;}
while (*q != '\0' && *q != ' ')
{
putchar(*q++);
}
if (p > arr)
{
putchar(' ');
}
}
putchar(mark);
putchar('\n');
return 0;
}
Question: Define an int function that removes all consecutive vowel repetitions from a string. The function should return the number of vowels removed and present the string without duplicates.
I am PT so Vogais is Vowels; Digite uma String is Write one String. A String sem duplicados fica assim ' %s ' e foram retiradas %d vogais is The string without duplicates is ' %s ' and where removed %d vowels.
Explanation: In portuguese we have some words with two consecutive vowels like: coordenador, coordenação (chqrlie example). But in thouse cases should be ignored in the context of this problem.
Problem: When I test a string like 'ooooo' it says the string without duplicate vogals is 'oo' and where removed 3 vowels. But it should be 'o' and 4 vowels removed. Another example with error is 'Estaa e umaa string coom duuuplicadoos', I am getting ' Esta e uma string com duplcdos ' and 8 vowels removed.
Note: This is a simple question so there isn't need to complicate. It only askes the consecutive duplicate vowels. The cases 'oOoO' -> 'oO' ,'abAb'->'abAb','abab' -> 'ab','aba'-> 'aba',... are in another chapter XD.
int Vogais(char *s) {
if (*s == 'A' || *s == 'a' || *s == 'E' || *s == 'e'
|| *s == 'I' || *s == 'i' || *s == 'O' || *s == 'o'
|| *s == 'U' || *s == 'u') return 1;
return 0;
}
int retiraVogaisRep(char *s) {
int res = 0;
for (int i = 0; i < strlen(s); i++) {
for (int j = i + 1; s[j] != '\0'; j++) {
if (s[i] == s[j] && Vogais(&s[j]) == 1) {
res++;
for (int k = j; s[k] != '\0'; k++) {
s[k] = s[k + 1];
}
}
}
}
return res;
}
int main() {
char s[38];
printf("Digite uma String:\n");
scanf("%[^\n]", s);
int res = retiraVogaisRep(s);
printf("A String sem duplicados fica assim ' %s ' e foram retiradas %d vogais.\n", s, res);
return 0;
}
Your code is too complicated: there is no need for nested loops for this task and you do not set the null terminator when shortening the string.
Here is a simpler version:
#include <stdio.h>
#include <string.h>
int retiraVogaisRep(char *s) {
int i, j; // use 2 running indices
char c, last = 0;
for (i = j = 0; (c = s[i]) != '\0'; i++) {
if (c != last || !strchr("aeiouAEIOU", c))
s[j++] = last = c;
}
s[j] = '\0'; // set the null terminator
return i - j; // return the number of bytes removed
}
int main() {
char s[100];
printf("Digite uma String:\n");
// read the user input safely with `fgets()`
if (!fgets(s, sizeof s, stdin))
return 1;
// strip the trailing newline if any
s[strcspn(s, "\n")] = '\0';
// remove duplicate consecutive vowels
int res = retiraVogaisRep(s);
printf("A String sem duplicados fica assim ' %s ' e foram retiradas %d vogais.\n", s, res);
return 0;
}
The question tag is C, but I will not post the actual code here.
The pseudocode:
function is_vowel(int c) {...}
start loop c = <src>
if next_char is past the last char then quit loop;
if is_vowel(c) and c == next_char and is_vowel(next_char)
then continue;
else
copy c to <dst>
You should elaborate on this, as the above is possibly having small issues. Nevertheless, I think this answer is somewhat shorter and gives an insight.
Update
The above is definitly have an issue, in that the next char does not copied to the output. The mistake is easy to correct, so I will leave it up to OP.
Update
Edited above code to indicate that OP wants to remove only identical duplicates. So, the case of a charcter is important.
Rather than a triple nested loop, consider a single walk down the string, looking for repeats.
#include <stdio.h>
#include <ctype.h>
int Vogais(unsigned char s) {
if (s == 'A' || s == 'a' || s == 'E' || s == 'e'
|| s == 'I' || s == 'i' || s == 'O' || s == 'o'
|| s == 'U' || s == 'u') return 1;
return 0;
}
int retiraVogaisRep(char *s) {
unsigned char *us = (unsigned char *) s;
unsigned char *dest = us;
int res = 0;
int prior = EOF;
while (*us) {
while (toupper(*us) == prior) {
us++;
res++;
}
prior = Vogais(*us) ? toupper(*us) : EOF;
*dest++ = *us++;
}
*dest = '\0';
return res;
}
int main() {
char buf[100] = "OoFreedaa";
printf("%d\t", retiraVogaisRep(buf));
printf("<%s>\n", buf);
return 0;
}
Output
3 <OFreda>
Remove consecutive duplicate vowels
You should use tolower function from ctype.h to check for vowels, that include the letter 'y', see below working code:
You can store previous character in prev and compare it to the current character, as you are case insensitive you store the tolower version.
#include <string.h>
#include <stdio.h>
#include <ctype.h>
int Vogais(char c){
return (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' || c == 'y') ;
}
int retiraVogaisRep (unsigned char *s){
if (*s == NULL)
return 0;
unsigned char t[256];
memset(t, 0, sizeof(t));
int res = 0;
int j = 0;
t[0] = s[0];
char prev = tolower(s[0]);
int len = strlen(s);
for (int i = 1; i < len; i++) {
char c = tolower(s[i]);
if (Vogais(c) && c == prev)
++res;
else
t[j++] = s[i];
prev = c;
}
memcpy(s, t, sizeof(t));
return res;
}
int main(){
char s[256];
printf("Digite uma String:\n");
scanf("%255[^\n]", s);
int res = retiraVogaisRep(s);
printf("Da String ' %s ' podem ser retiradas %d vogais.\n", s,res);
return 0;
}
Retaining the uppercase, using the Kernighan-copy
#include <stdio.h>
#include <string.h>
#include <ctype.h>
size_t remove_duplicate_vowels(char *str)
{
int old,new;
size_t dst,src;
old = 0;
for(dst=src=0; str[dst] = str[src]; old=new, src++ ) {
new = toupper( str[dst] );
if ( !strchr( "AEIOU", new )) { // Not a vowel
dst++; continue;
}
if ( new != old ) { // Not a repetition
dst++; continue;
}
}
return src - dst;
}
int main(int argc, char **argv)
{
char test[] = "Aaa bbBb CccCC d eEeee!";
char *arg;
size_t ret;
arg = argv[1] ? argv[1] : test;
ret = remove_duplicate_vowels(arg);
fprintf(stderr, "[%zu]: %s\n", ret, arg);
return 0;
}
I was writing a code that takes a sentence and reverses it, as an exercise. Here's what I wrote:
#include <stdio.h>
int main(void)
{
char a, sentence[100], sign;
char *c = sentence;
printf("Enter a sentence: ");
while ( (a = getchar()) != '\n' )
{
if ( a == '?' || a == '!' || a == '.')
{
sign = a;
break;
}
*c = a;
c++;
}
for (char *d = c; d >= sentence; d--)
{
if ( (d == sentence) && (*d != ' ') )
{
for (char *a = d; a < d + 99; a++)
{
if ( (*a == ' ') || (*a == '\n')) //code isn't reading the \n
{
break;
}
else
printf("%c", *a);
}
}
if ( (*d == ' ') && (d != c) && (d != sentence + 99) )
{
for (char *a = d+1; a <= c; a++)
{
if ( (*a == ' ') || (a == c))
{
printf(" ");
break;
}
else
printf("%c", *a);
}
}
}
printf("%c\n", sign);
return 0;
}
It works fine when I input a sentence with spaces in it:
Enter a sentence: This is a sentence
sentence a is This
However if I input a string with no spaces, like this:
Enter a sentence: Thisisasentence
I get an output with what was originally entered ('Thisisasentence'), followed by a lot of gibberish output. From what I understand, this is because the code doesn't go into the if ( (*a == ' ') || (*a == '\n') condition.
Why isn't the compiler reading the '\n'
The program works with a couple of changes.
In the while add *c = '\0'; after c++; to terminate the string.
Check for a == '\0' instead of '\n' as the while excludes the '\n'.
Added a check at the end of the while to make sure no more than 99 characters are allowed.
#include <stdio.h>
int main(void)
{
char a, sentence[100], sign;
char *c = sentence;
printf("Enter a sentence: ");
while ( (a = getchar()) != '\n' )
{
if ( a == '?' || a == '!' || a == '.')
{
sign = a;
break;
}
*c = a;
c++;
*c = '\0';//terminate
if ( c - sentence >= 99) {//make sure not too many characters
break;
}
}
for (char *d = c; d >= sentence; d--)//start at c and work back to sentence[0]
{
if ( (d == sentence) && (*d != ' ') )
{
for (char *a = d; !( *a == ' ' || *a == '\0'); a++)
{
printf("%c", *a);
}
}
if ( (*d == ' ') && (d != c) && (d != sentence + 99) )
{
for (char *a = d+1; a <= c; a++)
{
if ( (*a == ' ') || (a == c))
{
printf(" ");
break;
}
else
printf("%c", *a);
}
}
}
printf("%c\n", sign);
return 0;
}
It is probably best to split to work into two functions, one for reading a line of text and one for reversing it:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void reverse_string(char *str) {
/* skip null */
if (str == 0) {
return;
}
/* skip empty string */
if (*str == 0) {
return;
}
/* get range */
char *start = str;
char *end = start + strlen(str) - 1; /* -1 for \0 */
char temp;
/* reverse */
while (end > start) {
/* swap */
temp = *start;
*start = *end;
*end = temp;
/* move */
++start;
--end;
}
}
char *read(void) {
char *line = malloc(100), *linep = line;
size_t lenmax = 100, len = lenmax;
int c;
if (line == NULL)
return NULL;
for (;;) {
c = fgetc(stdin);
if (c == EOF)
break;
if (--len == 0) {
len = lenmax;
char *linen = realloc(linep, lenmax *= 2);
if (linen == NULL) {
free(linep);
return NULL;
}
line = linen + (line - linep);
linep = linen;
}
if ((*line++ = c) == '\n')
break;
}
*line = '\0';
return linep;
}
int main(void) {
printf("Enter a sentence:");
char *sentence = read();
reverse_string(sentence);
printf(sentence);
return 0;
}
Test 1
Enter a sentence:this is a sentence
ecnetnes a si siht
Test 2
Enter a sentence:thisisasentence
ecnetnesasisiht
I'm trying to split a sentence the user inputs to an array of words so I can later manipulate the words separately as strings.
The code is compiling but prints only garbage after the user input.
I tried debugging but don't see the problem. Can someone help me fix it?
#include <stdio.h>
#include <string.h>
int main() {
char str[1000];
int i = 0;
char rev[1000][1000];
int r = 0;
puts("Enter text:");
gets(str);
int k, length = 0;
printf_s("So the words are:\n");
while (str[i] != '\0') {
if (str[i] == ' ') {
k = i - length;
do {
rev[r][k] = (str[k]);
k++;
} while (str[k] != ' ');
printf(" ");
length = (-1);
r++;
} else
if (str[i + 1] == '\0') {
k = i - length;
do {
rev[r][k] = (str[k]);
k++;
} while (str[k] != '\0');
length = 0;
r++;
}
length++;
i++;
}
for (int r = 0; r < 1000; r++)
printf("%s ", rev[r]);
return 0;
}
fix like this
#include <stdio.h>
int main(void) {
char str[1000];
char rev[1000][1000];
puts("Enter text:");
fgets(str, sizeof str, stdin);//Use fgets instead of gets. It has already been abolished.
int r = 0;
int k = 0;
for(int i = 0; str[i] != '\0'; ++i){
if (str[i] == ' ' || str[i] == '\n'){//is delimiter
if(k != 0){
rev[r++][k] = '\0';//add null-terminator and increment rows
k = 0;//reset store position
}
} else {
rev[r][k++] = str[i];
}
}
if(k != 0)//Lastly there was no delimiter
rev[r++][k] = '\0';
puts("So the words are:");
for (int i = 0; i < r; i++){
printf("%s", rev[i]);
if(i < r - 2)
printf(", ");
else if(i == r - 2)
printf(" and ");
}
return 0;
}
Replace you declaration
char rev[1000][1000];
with
char * rev[1000]; // We will need pointers only
int i = 0; // Index to previous array
and all your code after
puts( "Enter text:" );
with this:
fgets( str, 998, stdin ); // Safe way; don't use gets(str)
const char delim[] = ",; "; // Possible delimiters - comma, semicolon, space
char *word;
/* Get the first word */
word = strtok( str, delim );
rev[i++] = word;
/* Get the next words */
while( word != NULL )
{
word = strtok( NULL, delim );
rev[i++] = word;
}
/* Testing */
for (int r = 0; r < i - 1; r++)
printf( "%s\n", rev[r] );
return 0
}
As you can see, all dirty work is done with the strtok() function ("string to tokens") which walks through other and other words ("tokens"), recognizing them as delimited by one or more characters from the string delim.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int count_spaces(char *str)
{
if (str == NULL || strlen(str) <= 0)
return (0);
int i = 0, count = 0;
while (str[i])
{
if (str[i] == ' ')
count++;
i++;
}
return (count);
}
int count_char_from_pos(char *str, int pos)
{
if (str == NULL || strlen(str) <= 0)
return 0;
int i = pos, count = 0;
while (str[i] && str[i] != ' ')
{
count++;
i++;
}
return count;
}
char **get_words(char *str)
{
if (str == NULL || strlen(str) <= 0)
{
printf("Bad string inputed");
return NULL;
}
int i = 0, j = 0, k = 0;
char **dest;
if ((dest = malloc(sizeof(char*) * (count_spaces(str) + 1))) == NULL
|| (dest[0] = malloc(sizeof(char) * (count_char_from_pos(str, 0) + 1))) == NULL)
{
printf("Malloc failed\n");
return NULL;
}
while (str[i])
{
if (str[i] == ' ') {
dest[j++][k] = '\0';
if ((dest[j] = malloc(sizeof(char) * (count_char_from_pos(str, i) + 1))) == NULL)
{
printf("Malloc failed\n");
return NULL;
}
k = 0;
}
else {
dest[j][k++] = str[i];
}
i++;
}
dest[j][k] = 0;
dest[j + 1] = NULL;
return dest;
}
int main(void) {
char *line = NULL;
size_t n = 0;
getline(&line, &n, stdin);
printf("%s\n", line);
line[strlen(line) - 1] = 0;
printf("%s\n", line);
char **tab = get_words(line);
int i = 0;
while (tab[i])
{
printf("%s\n", tab[i++]);
}
}
here is a long but fully working example
get the user input
then send it to get_words function. It will get the number of words, the number of characters for each words, allocate everything in memory and writes chars then return it. You get a char ** and prints it just tested it it works
If you wish to split a string into an array of strings, you should consider the strtok function from #include <string.h>. The strtok function will the split the string on the given delimiter(s). For your case, it would the " ".
Using the strtok example from Tutorials Point:
#include <string.h>
#include <stdio.h>
int main(){
char str[80] = "This is - www.tutorialspoint.com - website";//The string you wish to split
const char s[] = "-";//The thing you want it to split from. But there is no need to this.
char *token;//Storing the string
/* get the first token */
token = strtok(str, s);//Split str one time using the delimiter s
/* walk through other tokens */
while( token != NULL )
{
printf( " %s\n", token );//Print the string
token = strtok(NULL, s);//Split the string again using the delimiter
}
return(0);
}
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 8 years ago.
Improve this question
I am trying to take a string input from user and then reverse only the words starting with a vowel.Then reprint the changed string.I have used the strtok() function to separate the words from the string.But reversing the words,seems to be a problem....I have written a code for this program,but it is having runtime error.So,it will be really useful,if anyone could help me correct my code or provide me with a solution.
Here is my code:
#include <stdio.h>
#include <string.h>
void reverse(char *tok);
int length(char *t);
int main()
{
char sen[50];
const char s[2] = " ";
int i;
printf("Enter a Sentence: ");
gets(sen);
char *token;
token = strtok(sen, s);
printf("Output: ");
while (token != 0)
{
char z[20] =
{ *token };
for (i = 0;; i++)
{
if (z[i] == ' ')
{
z[i] = '\0';
break;
}
}
if (z[0] == 'a' || z[0] == 'A' || z[0] == 'e' || z[0] == 'E' || z[0] == 'i'
|| z[0] == 'I' || z[0] == 'o' || z[0] == 'O' || z[0] == 'u'
|| z[0] == 'U')
{
reverse(token);
}
else
printf("%s ", *token);
token = strtok(NULL, s);
}
printf("\n");
return 0;
}
//function for reversing the particular parts of string
void reverse(char *tok)
{
char x[20] =
{ *tok };
int i, j, len;
char temp;
for (i = 0;; i++)
{
if (x[i] == ' ')
{
x[i] = '\0';
break;
}
}
len = length(tok);
j = len - 1;
for (i = 0; x[i] != len / 2; i++)
{
temp = x[i];
x[i] = x[j];
x[j] = temp;
j--;
}
printf("%s", x);
printf(" ");
}
//function for determining the length of the token string
int length(char *t)
{
int i = 0;
char y[20] =
{ *t };
for (;; i++)
{
if (y[i] == ' ')
{
y[i] = '\0';
break;
}
}
while (y[i] == '\0')
{
i++;
}
return i;
}
This line
printf("%s ", *token);
passes a char where a 0-terminated char[] is expected.
The lesson learned is: Always compile with all warnings on! (-Wall -Wextra -pedantic for gcc)
Problem lies in this line:
if(z[i]==' ')
You've split with the token ' ', so that means there is no ' ' in z[]. So the loop never ends.
#include <stdio.h>
#include <string.h>
void reverse(char *tok);
int length(char *t);
int main(){
char sen[50];
const char s[2] = " ";
printf("Enter a Sentence: ");
scanf("%49[^\n]", sen);//gets(sen); //"gets" : Obsolete !
char *token = strtok(sen, s);
printf("Output: ");
while (token != NULL){
char z = *token;
if (z == 'A' || z == 'E' || z == 'I' || z == 'O' || z == 'U' ||
z == 'a' || z == 'e' || z == 'i' || z == 'o' || z == 'u'){
reverse(token);//print by this function
} else {
printf("%s ", token);
}
token = strtok(NULL, s);
}
printf("\n");
return 0;
}
void reverse(char *tok){//original not change
int i, len = length(tok);
char x[len + 1];
for (i = 0; i<len; ++i){
x[i] = tok[len-i-1];
}
x[i]='\0';
printf("%s ", x);
}
int length(char *t){//use strlen
int i;
for(i=0;*t;++i, ++t)
;
return i;
}