I am writing a small C code for class that plays Hangman with an already input name. One section requires I allow the output of the input phrase with * in the place of all letters, but not punctuation. Similarly, at the end of the phrase, the name of the user is put in parentheses and is meant to be printed as is. The first section of the code works fine, the first while loop which places the asterisks, but the second while loop seems to fail every time and seems to store nonsense and random characters everytime the program is run. Here is the program I have so far.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int guesses = 3;
int limit = 41;
char quote[42] = "I just wrote this game in C! (Josh Masher)";
char strArr[42];
char *quoP;
quoP = "e[0];
char *strP;
strP = &strArr[0];
while (*quoP != '.' && *quoP != '!' && *quoP != '?') {
if (isalpha(*quoP)) {
*strP = '*';
} else if (*quoP == ' ' || *quoP == ',') {
*strP = *quoP;
}
strP++;
quoP++;
}
while (*quoP != NULL) {
*strP = *quoP;
strP++;
quoP++;
}
}
any ideas?
EDIT
I rewrote the code slightly, and erased the random character problem, but it is more complicated now.
int main()
{
int guesses = 3;
int limit = 41;
char quote[42] = "I just wrote this game in C! (Alex Butler)\0";
char strArr[42];
char *quoP;
quoP = "e[0];
char *strP;
strP = &strArr[0];
int counter = 0;
while (*quoP != '\0') {
if (*quoP == '.' || *quoP == '!' || *quoP == '?' || counter == 1) {
counter = 1;
}
if (isalpha(*quoP)) {
if (counter == 0) {
*strP = '*';
} else if (counter == 1) {
*strP = *quoP;
}
} else {
*strP = *quoP;
}
printf("%c", *strP);
strP++;
quoP++;
}
}
Add *strP = '\0' after the last while loop to terminate the string.
Also, (*quoP != NULL) should be (*quoP != '\0') . The type of NULL is pointer, the type of *quoP is character. Your program will still work, but it's misleading.
Also might want to include ctype.h
Good luck with the rest of your project.
The first loop doesn't work fine. If it encounters unhandled punctuation (such as &), it will skip right over and leave junk there.
You do not null-terminate the string either, as others have pointed out in the comments. You would do better to copy the string first (with strncpy) and then stamp characters with * as you deem appropriate. That means you only have one loop, and it'll be a lot simpler:
strncpy( strArr, quote, sizeof(strArr) );
for( char *s = strArr; !strchr(".!?", *s); s++ )
{
if( isalpha(*s) ) *s = '*';
}
Also, NULL is a pointer. Null-termination is an unfortunate name for this. You can write the value 0 or '\0', but not NULL.
Related
I would like to print the remaining string by a deliminator.
The expected output should be:
String
in
C
int main()
{
/* loop over a string using subscript*/
char *s = "String in C";
char* ps;
ps = s;
while(*ps != ' ')
{
printf("%c",*ps);
ps++;
}
}
I can get the first String.
How can I get the rest of it?
This is not the best solution but it works.
#include <stdio.h>
int main()
{
char *s = "String in C";
char *ps;
ps = s;
while (*ps != '\0')
{
if (*ps == ' ')
{
printf("\n");
*ps++;
}
else
{
printf("%c", *ps);
ps++;
}
}
}
You need to examine the logic of your program.
What you are doing right now is you stop iterating right after the first word, when the first space is encountered; that is what while(*ps != ' ') does.
Instead, you can iterate through the whole string, taking advantage of the fact that a string in C ends with a \0, i.e. while (*ps != '\0').
Inside the while you can first test if the character is a blank, and if it is you can advance the pointer and skip to the next character using continue:
if (*ps == ' ') {
printf("\n");
ps++;
continue;
}
Note that the code also prints a newline for readability. This if should also be first thing in the loop and this way it will also skip trailing blanks.
The rest of the code is what you have now, though you may want to add another newline printf after the while loop.
I'm new to C, I have been asked to make a program in C asking to print each letter after a '.' after a user has entered an input.
For example if the user enters a..bcd..e.f..gh the output should be befg
which is the exact example I have been given in class.
I assume this would need to use pointers but I am unsure how to deal with this question, here is what I have tried to do so far. I know it is not correct, please help me understand how to use pointers to deal with this question.
#include <stdio.h>
int main() {
char *c, count =0;
printf("enter some characters");
scanf("%s", &c);
while( c != EOF ) {
if (c != '.') {
count ++;
}
else; {
printf("%s", c);
}
}
}
The program can look the following way
#include <stdio.h>
#define N 100
int main( void )
{
char s[N];
const char DOT = '.';
printf( "Enter some characters: " );
fgets( s, N, stdin );
for ( char *p = s; *p; ++p )
{
if ( p[0] == DOT && p[1] != DOT ) putchar( p[1] );
}
putchar( '\n' );
}
Its output might look like
Enter some characters: a..bcd..e.f..gh
befg
Take into account that here any symbol after a dot (except the dot itself) is printed. You can add a check that there is a letter after a dot.
You don't really need pointers for this, or even an array. Basically it's a simple state engine: read each character, if '.' is encountered, set a flag so the next character is printed.
#include <stdio.h>
int main() {
int c, flag = 0;
while ((c = getchar()) != EOF) {
if (c == '.')
flag = 1;
else if (flag) {
putchar(c);
flag = 0;
}
}
return 0;
}
There are some errors in your code:
- char* c means a pointer to one or more characters.
But where does it point to?
- scanf reads a string up to an "white space". White space characters are the space itself, a newline, a tab character or an EOF. scanf expects a format string and a pointer to a place in memory where it places what it reads. In your case c points to an undefined place and will overwrite whatever there is in memory.
- why do you place a ";" after the else? The else clause will end with the ";". So your program will do the print every time.
It helps you a lot if you format your code in a more readable way and give the variable names that give hint what they are used for.
Another very important thing is to initialize every variable that you declare. Errors with uninitialized variables are sometimes very hard to find.
I would do it this way:
#include <stdio.h>
int main(int argc, char* argv[])
{
// I read every single character. The getchar function returns an int!
int c = 0;
// This marks the program state whether we must print the next character or not
bool printNext = false;
printf("enter some characters");
// We read characters until the buffer is empty (EOF is an integer -1)
do
{
// Read a single character
c = getchar();
if ( c == '.')
{
// After a point we change our state flag, so we know we have to print the next character
printNext = true;
}
else if( c != EOF )
{
// When the character is neither a point nor the EOF we check the state
if( printNext )
{
// print the character
printf( "%c", c );
// reset the state flag
printNext = false;
}
}
// read until the EOF occurs.
}
while( c != EOF );
}
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main()
{
char letter;
char *c;
c = malloc(256);
printf("enter the string : ");
scanf("%s", c);
while( (letter=*(c)) != '\0' )
{
if (letter == '.')
{
c++;
letter=*c;
if(letter!='.')
printf("%c",letter);
else
{
while(letter=='.')
{
c++;
letter=*c;
}
printf("%c",letter);
}
}
c++;
}
printf("\n");
}
A friend of mine gave me a task to write a program to
replace "a", "an", "the" with blank space in a text file in C.
I wrote that program, but that went too lengthy as I checked "a", "an", "the" individually.
For example, I replaced "a" by
NOTE: fs is pointer to the source file and ft is pointer to the target file.
while(fgets(str, 100, fs) != NULL)
{
for(i = 0; str[i] != '\0'; i++)
{
if (str[i] == ' ' ||
str[i] == '.' ||
str[i] == ',' ||
str[i] == '\n' ||
str[i] == '\t')
{
if (str[i+1] == 'a' || str[i+1] == 'A')
{
if (str[i+2] == ' ' ||
str[i+2] == '.' ||
str[i+2] == ',' ||
str[i+2] == EOF ||
str[i+2] == '\0' ||
str[i+2]== '\n' ||
str[i+2]== '\t')
{
str[i+1]=' ';
}
}
}
}
fputs(str,ft);
}
Is there a shorter way to do the same?
Take care of the fact that "a", "an", "the" can be the first words in the source file.
Use the fscanf and fprintf functions so that scanning the file would be easy for you and you can easily check for 'a, an, the':
char s[50];
while(fscanf(fp, "%s", s) != EOF)
{
if(strcmp(s, "a") == 0 || strcmp(s, "an") == 0 || strcmp(s, "the") == 0)
{
char c = ' ';
fprintf(ft, "%s", c);
}
else
{
fprintf(ft, "%s", s);
}
}
You can read the input char-by-char, using for example getchar, or always remember the last few chars, even if they were in the previous buffer. This way you need to remember the previous two chars, and the current char in a little "rolling-array", that you would reset at each word boundary.
Using a fixed sized buffer with fgets, or fscanf, you need a lot of codeing to handle special cases. There are a few, for example the lines don't start with space or tab, but a line parhaps starts with "the". In that case, there will be no such character before the word. The same thing is true about whitespace following a word. You can get around these things by allocating a bit more space for the buffer, fill the first char with ' ' , and call fgets this way:
fgets(str + 1, 99, fs)
But you still have the problem of words at boundaries, where your buffer ends with "... t" and the next fgets gives you "he ..." .
Just keep an array of 3 chars, and the current length of the array, resetting the length to zero at each word boundary.
I think this code works for a reasonably plausible definition of the problem:
#include <ctype.h>
#include <stdio.h>
#include <string.h>
static char const *words[] = { "a", "the", "an" };
enum { NUM_WORDS = sizeof(words) / sizeof(words[0]) };
static void mapword(char *word, int len)
{
char lower[256];
word[len] = '\0';
for (int i = 0; i <= len; i++)
lower[i] = tolower(word[i]);
for (int i = 0; i < NUM_WORDS; i++)
{
if (strcmp(words[i], lower) == 0)
{
putchar(' ');
return;
}
}
fputs(word, stdout);
}
int main(void)
{
char word[256];
int c;
size_t nletters = 0;
while ((c = getchar()) != EOF)
{
/*
** This would break if you enter a word with 256 characters
** ending in 'a' because the word would be split after 255
** characters and the trailing 'a' would then match the
** next buffer full, which is an awfully improbable event.
*/
if (!isalpha(c) || nletters >= sizeof(word)-1)
{
if (nletters > 0)
{
mapword(word, nletters);
nletters = 0;
}
putchar(c);
}
else
word[nletters++] = c;
}
if (nletters > 0)
{
/*
** Since a text file should end with a newline, the program
** should not get here!
*/
mapword(word, nletters);
}
return 0;
}
For example, given the first three lines of the question as input:
A friend of mine gave me a task to write a program to
replace "a", "an", "the" with blank space in a text file in c.
I wrote that program but that went too lengthy as I checked "a", "an", "the" individually.
the output from the program is:
friend of mine gave me task to write program to
replace " ", " ", " " with blank space in text file in c.
I wrote that program but that went too lengthy as I checked " ", " ", " " individually.
If you want to use some system command then your life is easy. sed is linux command to serve your requirement.
You can do as follows
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char * argv[])
{
system("sed 's/an//g;s/a//g;s/the//g' file");
}
If file contain
replace “a”, “an”, “the” with blank space in a text file
Output is
replce “”, “”, “” with blk spce in text file
Caution : This code replace space every where when it found matching pattern.So it not check for matching whole word.
This question already has answers here:
Reverse the ordering of words in a string
(48 answers)
Closed 8 years ago.
I need a program to reverse the words in a string.
Input: My car is fast
Output: fast is car My
int printRword(char * line) {
for(; *line; line++) {
if(*line == ' ') {
printRword(line + 1);
printf("%s", line);
return 0; // after you find the space set it to null
}
}
}
int main(void) {
char *line = "this is a long line that we are working with\n";
printf("%s", line);
printRword(line);
return 0;
}
I know I need to set space to null after I find it, and I've tried printRword(line + 1) = '\0';
and that doesn't work
any suggestions?
You could reverse the whole string, and then reverse each individual word, having the effect of reversing the order of the words but leaving the letters in each word in the correct order. Not the most efficient, perhaps, but conceptually clean -- and not language dependent!
Find the modified working code:
int printRword(char * line)
{
char tempbuf[100]; //Here length i have hardcoded to 100
char *ptr;
strcpy(tempbuf,line); //copied to tempbuf to keep the original string unmodified
//Replace the \n with the null character
ptr = strrchr(tempbuf,'\n');
if(ptr != NULL)
{
*ptr = '\0';
}
while(*tempbuf != '\0')
{
ptr = strrchr(tempbuf,' ');
if(NULL != ptr)
{
*ptr = '\0';
ptr++;
printf("%s ",ptr);
}
else
{
printf("%s\n",tempbuf);
*tempbuf ='\0';
}
}
}
test result:
atharv#atharv-Inspiron-5423:~/Programming$ ./a.out
this is a long line that we are working with
with working are we that line long a is this
atharv#atharv-Inspiron-5423:~/Programming$
You could go through the string character-by-character, replacing the spaces by ASCII NUL characters (C's string terminators), and recording the next position in each case (by pushing onto a stack), thus recording the beginning of each word. When you get to the end of the string, you can then go backwards through the list of “start-of-word” positions (perhaps by popping off the stack), printing out the word each time followed by a space.
This is the basic idea. If you have to handle multiple spaces between words or newlines, it gets a little bit more complicated, but not much.
I modified your code using the same recursive approach to get the desired output, just added a function that would print only till next space.. there must be a function for this already but i am not aware of it.
#include <stdio.h>
void printTillNextSpace(char *s){
while(*s != ' ' && *s != '\0' && *s != '\n')
printf("%c",*s++);
printf("%c",' ');
}
int printRword(char * line){
char* start = line;
for(;*line; line++){
if(*line == ' '){
printRword(line + 1);
printTillNextSpace(start);
start = line + 1;
return 0; // after you find the space set it to null
}
}
printTillNextSpace(start);
}
int main(){
char * line = "this is a long line that we are working with\n";
printf("%s", line);
printRword(line);
return 0;
}
Recently in an interview, I was asked to write a code to reverse an unbounded string without checking for the null character. I don't know the length of the string and cannot use any library function in any form..
I wrote the following code ( which I know is incorrect due to many reasons, one being I am not terminating the string with '\0', instead I am terminating it with CTRL+Z or CTRL+D)
while(scanf("%c",arr[i++])!=-1);
for(i--;i>=0;i--)
puts(arr[i]);
What can be the possible algorithm !!
Maybe something like:
void
reverse_print(const char* string) {
if (*string == 0) {
return;
}
reverse_print(string + 1);
putchar(*string);
}
Or, reading the string from input:
void
reverse_print() {
char c;
if (1 != scanf("%c", &c)) {
return;
}
reverse_print();
putchar(c);
}
It seems you are reading the string from input, and trying to print it.
You can just count the number of characters, and treat it like it was a normal array, something along the lines of:
int main() {
int i = 0;
char arr[256];
while(scanf("%c",arr + (i++))!=-1);
for(i = i-1; i+1; i--) putchar(arr[i]);
return 0;
}
If the array is completely unbounded, you will have to make sure you are not out of space, and if you are - reallocate it.
You can also add a NULL terminator manually when you are done. Since, it is not checking for it, you should be fine with the requirements.
#include <stdio.h>
int main(void)
{
char* string1 = "This is me the right guy!! understood !!!";
char* string = string1;
char *nonstring = "\x01\x05\x0a\x15";
int len = 0;
while ((*string ^ nonstring[0]) && (*string ^ nonstring[1])
&& (*string ^ nonstring[2]) && (*string ^ nonstring[3])
&& (*string ^ nonstring[4]))
{
len++;
string++;
}
//printf("%d\n", len);
while(len)
{
printf("%c", string1[--len]);
}
return 0;
}