Make 1st letter the last letter in the word - c

I need help rotating words so they output with the 1st letter at the end.
I have a file called flip.txt
backpack
carpet
rotate
and i want to be able to enter ./RotateWord < flip.txt (in terminal) and it should output
ackpackb
arpetc
otater
I was able to get it to output the words with the 1st letter missing . How to i make it output the 1st letter at the end?
Heres my code
#include <stdio.h>
#define BUFFER_SIZE 81
int main(int argc, char **argv) {
char string[BUFFER_SIZE];
while(fgets(string, BUFFER_SIZE, stdin) > 0) {
int numChars = 0;
while(string[numChars] && string[numChars] != '\n')
++numChars;
int i;
for(i = 1; i < numChars; ++i){
if (string[i] == '\n'){
putchar(string[0]);
putchar('\n');
}
else {
putchar(string[i]);
}
}
putchar('\n');
fflush(stdout);
}
return 0;
}

You can use strcspn to get rid of the \n.
string[strcspn(string,"\n")]=0;
If you want to print the string in that way - do this two line. (You can merge it in one line too).
printf("%s",string+1);
printf("%c\n",string[0]);
The code will be
while(fgets(string, BUFFER_SIZE, stdin) != NULL) {
string[strcspn(string,"\n")]=0;
printf("%s%c\n",string+1,string[0]);
fflush(stdout);
}
Why your code didn't work?
The thing is as per your code the if block is never executed. So you will never get the first character printed. The previous while loop simply increments the variable as long as it doesn't meet the \n. Then in the next loop you iterate over them < numChars and then expect to see the \n, which won't be the case now.
Changing your code this would work
while(fgets(string, BUFFER_SIZE, stdin) != NULL) {
for(int i = 1; string[i]; ++i){
if (string[i] == '\n'){
putchar(string[0]);
putchar('\n');
}
else {
putchar(string[i]);
}
}
fflush(stdout);
}
Earlier you were putting \n after every character that you print. It should be only after the last character.
Note:
fgets returns char* - in case of error it returns NULL. So to check if fgets is successful or not you should do a null check.

It it possible that you're not counting the final '\n' character when you
while(string[numChars] && string[numChars] != '\n')
++numChars;
?
If so, you never hit
if (string[i] == '\n'){
putchar(string[0]);
putchar('\n');
}
because your loop stops one early.

In the for loop run till
for(i=1,i<=numChars,i++)
This is because the if statement does not get executed as the index does not reach the newline character.
Thus the complete code is as follows:
#include <stdio.h>
#define BUFFER_SIZE 81
int main(int argc, char **argv) {
char string[BUFFER_SIZE];
while(fgets(string, BUFFER_SIZE, stdin) > 0) {
int numChars = 0;
while(string[numChars] && string[numChars] != '\n')
++numChars;
int i;
for(i = 1; i <= numChars; ++i){
if (string[i] == '\n'){
putchar(string[0]);
putchar('\n');
}
else {
putchar(string[i]);
}
}
//putchar('\n');
fflush(stdout);
}
return 0;
}
Also there is no need of extra
putchar('\n');

Related

How to use fgets() function so that it only reads 12 characters per line?

I have a file that contains the following words:
Theendsherethiswillnotjaksdjlasdfjkl;asdjfklasdjfkl;asdfjl;
these
are
the
Below is my code :
int i = 0;
bool duplicateFound = false;
while(fgets(line,12,fp)){
for (int j = 0; j < i; j++){
if (strcmp(wordList[j], line) == 0){
duplicateFound = true;
printf("Duplicate Found on Line %d : %s\n", j, wordList[j]);
}
}
if (duplicateFound == false){
strcpy(wordList[i], line);
printf("%s", wordList[i]);
}
i++;*/
printf("%s", line);
}
I am using line to save each word so that I can later check it for duplicates in the array.
I want it so that the function only reads up to 12 characters on each line but it outputs the following output.
ACTUAL OUTPUT :
Theendsherethiswillnotjaksdjlasdfjkl;asdjfklasdjfkl;asdfjl;
these
are
the
EXPECTED OUTPUT:
Theendsheret
these
are
the
You really should just call fgets and then do line[12] = '\0', but that doesn't cleanly deal with input that has long lines. One option is to simply abort if fgets ever returns a partial line (eg, if strchr(line, '\n') returns NULL).
If you want to handle long lines, you can just discard data with getchar until you see a newline. Assuming that you don't want to consider the newline to be one of the 12 characters, you could do something like:
#include <stdio.h>
#include <string.h>
int
main(void)
{
char line[13];
while( fgets(line, 13, stdin) ) {
char *c = strchr(line, '\n');
int ch;
if( c == NULL ) while( (ch = getchar()) != EOF ) {
if( ch == '\n' ) {
break;
}
} else {
*c = '\0';
}
if( printf("%s\n", line) < 0 ) {
break;
}
}
return ferror(stdout) || ferror(stdin) || fclose(stdout) || fclose(stdin);
}

tempWord[0]='\0' Does not reset String somehow

I wrote a program in C, The expected result should be:
$ cat poem.txt
Said Hamlet to Ophelia,
I'll draw a sketch of thee,
What kind of pencil shall I use?
2B or not 2B?
$ ./censor Ophelia < poem.txt
Said Hamlet to CENSORED,
I'll draw a sketch of thee,
What kind of pencil shall I use?
2B or not 2B?
But I got this:
$ ./censor Ophelia < poem.txt
Said Hamlet tomlet CENSORED,
I'lllia drawlia arawlia sketcha ofetcha theecha,
Whatcha kindcha ofndcha pencila shallla Ihallla usellla?
2Bsellla orellla notllla 2Botllla?
I use tempWord to store every word and compare it with the word that needs to be censored. Then I use tempWord[0]='\0' to reset the temp String, so that I can do another comparison. But it seems not working. Can anyone help?
# include <stdio.h>
# include <string.h>
int compareWord(char *list1, char *list2);
int printWord(char *list);
int main(int argc, char *argv[]) {
int character = 0;
char tempWord[128];
int count = 0;
while (character != EOF) {
character = getchar();
if ((character <= 'z' && character >= 'a') ||
(character <= 'Z' && character >= 'A') ||
character == 39) {
tempWord[count] = character;
count++;
} else {
if (count != 0 && compareWord(tempWord, argv[1])) {
printf("CENSORED");
count = 0;
tempWord[0] = '\0';
}
if (count != 0 && !compareWord(tempWord, argv[1])) {
printWord(tempWord);
count = 0;
tempWord[0] = '\0';
}
if (count == 0) {
printf("%c", character);
}
}
}
return 0;
}
int printWord(char *list) {
// print function
}
int compareWord(char *list1, char *list2) {
// compareWord function
}
There are multiple issues in your code:
You do not test for end of file at the right spot: if getc() returns EOF, you should exit the loop immediately instead of processing EOF and exiting at the next iteration. The classic C idiom to do this is:
while ((character = getchar()) != EOF) {
...
For portability and readability, you should use isalpha() from <ctype.h> to check if the byte is a letter and avoid hardcoding the value of the value of the apostrophe as 39, use '\'' instead.
You have a potential buffer overflow when storing the bytes into the tempWord array. You should compare the offset with the buffer size.
You do not null terminate tempWord, hence the compareWord() function cannot determine the length of the first string. The behavior is undefined.
You do not check if a command line argument was provided.
The second test is redundant: you could just use an else clause.
You have undefined behavior when printing the contents of tempWord[] because of the lack of null termination. This explains the unexpected behavior, but you might have much worse consequences.
printWord just prints a C string, use fputs().
The compWord function is essentially the same as strcmp(a, b) == 0.
Here is a simplified and corrected version:
#include <ctype.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
char tempWord[128];
size_t count = 0;
int c;
while ((c = getchar()) != EOF) {
if (isalpha(c) || c == '\'') {
if (count < sizeof(tempWord) - 1) {
tempWord[count++] = c;
}
} else {
tempWord[count] = '\0';
if (argc > 1 && strcmp(tempWord, argv[1]) == 0) {
printf("CENSORED");
} else {
fputs(tempWord, stdout);
}
count = 0;
putchar(c);
}
}
return 0;
}
EDIT: chux rightfully commented that the above code does not handle 2 special cases:
words that are too long are truncated in the output.
the last word is omitted if it falls exactly at the end of file.
I also realized the program does not handle the case of long words passed on the command line.
Here is a different approach without a buffer that fixes these shortcomings:
#include <ctype.h>
#include <stdio.h>
int main(int argc, char *argv[]) {
const char *word = (argc > 1) ? argv[1] : "";
int count = 0;
int c;
for (;;) {
c = getchar();
if (isalpha(c) || c == '\'') {
if (count >= 0 && (unsigned char)word[count] == c) {
count++;
} else {
if (count > 0) {
printf("%.*s", count, word);
}
count = -1;
putchar(c);
}
} else {
if (count > 0) {
if (word[count] == '\0') {
printf("CENSORED");
} else {
printf("%.*s", count, word);
}
}
if (c == EOF)
break;
count = 0;
putchar(c);
}
}
return 0;
}
tempWord[0] = '\0';
It will not reset the variable to null. It just assign the '\0' to the first position. But The values which are assigned are still in memory only. Only the first position is assigned to '\0'. So, to reset the character array try the below.
memset(tempWord, 0, 128);
Add the above line instead of your tempWord[0] = '\0'.
And also this will solves you don't need to add the '\0' at end of each word. This itself will work. But for the first time your have to reset the character array using the same memset function. Before entering to the loop you have to set the tempWord to null using the memset function.
Using tempWord[0]='\0' will not reset the whole array, just the first element. Looking at your code, there are 2 ways you could go forward, either reset the whole array by using memset:
memset(tempWord, 0, sizeof tempWord);
or
memset(tempWord, 0, 128);
(or you can only clear it by the size of last word, also it needs string.h which you have already included),
Or you could just set the element after the length of 'current word' to be '\0' (ex, if current word is the then set tempWord[3]='\0', since strlen checks the string till null char only) which can be placed before those 2 ifs checking if the strings are equal or not, your new while loop will look like this:
{
character = getchar();
if((character<='z' && character>='a')||(character<='Z' && character>='A')||character == 39)
{
tempWord[count]=character;
count++;
}else {
tempWord[count]='\0';
if(count!=0 && compareWord(tempWord, argv[1]))
{
printf("CENSORED");
count=0;
}
if(count!=0 && !compareWord(tempWord, argv[1]))
{
printWord(tempWord);
count=0;
}
if (count==0)
{
printf("%c", character);
}
}
}
(it works, tested)

fgets and chdir acting strangely together in C

I am currently creating a simple shell for homework and I've run into a problem. Here is a snippet of code with the pieces that pertain to the problem (I may have forgotten some pieces please tell me if you see anything missing):
eatWrd returns the first word from a string, and takes that word out of the string.
wrdCount, as implied, returns the number of words in a string.
if either of these codes are necessary for a response I can post them, just please tell me, I am almost 100% positive they are not the cause of the problem.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX 100
int main(void)
{
char input[MAX];
char *argm[MAX];
memset(input, 0, sizeof(input));
memset(argm, 0, sizeof(argm));
while(1){
printf("cmd:\n");
fgets(input, MAX-1, stdin);
for(i=0;i < wrdCount(input); i++){
argm[i] = eatWrd(input);
}
argm[i] = NULL;
if (!strncmp(argm[0],"cd" , 2)){
chdir(argm[1]);
}
if (!strncmp(argm[0],"exit", 4)){
exit(0);
}
memset(input, 0, sizeof(input));
memset(argm, 0, sizeof(argm));
}
}
Anyways, this loop works for lots of other commands using execvp, (such as cat, ls, etc.), when I use cd, it works as expected, except when I try to exit the shell, it takes multiple exit calls to actually get out. (as it turns out, the number of exit calls is exactly equal to the number of times I call cd). It only takes one exit call when I don't use cd during a session. I'm not really sure what's going on, any help is appreciated, thanks.
Here is eatWrd:
char* eatWrd(char * cmd)
{
int i = 0; // i keeps track of position in cmd
int count = 0; // count keeps track of position of second word
char rest[MAX_LINE]; // rest will hold cmd without the first word
char * word = (char *) malloc(MAX_LINE); //word will hold the first word
sscanf(cmd, "%s", word); //scan the first word into word
// iterate through white spaces, then first word, then the following white spaces
while(cmd[i] == ' ' || cmd[i] == '\t'){
i++;
count++;
}
while(cmd[i] != ' ' && cmd[i] != '\t' && cmd[i] != '\n' && cmd[i] != '\0'){
i++;
count++;
}
while(cmd[i] == ' ' || cmd[i] == '\t'){
i++;
count++;
}
// copy the rest of cmd into rest
while(cmd[i] != '\n' && cmd[i] != '\0'){
rest[i-count] = cmd[i];
i++;
}
rest[i-count] = '\0';
memset(cmd, 0, MAX_LINE);
strcpy(cmd, rest); //move rest into cmd
return word; //return word
}
And here is wrdCount:
int wrdCount(char *sent)
{
char *i = sent;
int words = 0;
//keep iterating through the string,
//increasing the count if a word and white spaces are passed,
// until the string is finished.
while(1){
while(*i == ' ' || *i == '\t') i++;
if(*i == '\n' || *i == '\0') break;
words++;
while(*i != ' ' && *i != '\t' && *i != '\n' && *i != '\0') i++;
}
return words;
}
This variation on your code works for me:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#define MAX 100
char *eatWrd(char **line) {
char *next_c = *line;
char *word_start = NULL;
while (isspace(*next_c)) next_c += 1;
if (*next_c) {
word_start = next_c;
do {
next_c += 1;
} while (*next_c && ! isspace(*next_c));
*next_c = '\0';
*line = next_c + 1;
}
return word_start;
}
int main(void)
{
char input[MAX];
char *argm[MAX];
while(1) {
int word_count = 0;
char *next_input = input;
printf("cmd:\n");
fgets(input, MAX, stdin);
do {
argm[word_count] = eatWrd(&next_input);
} while (argm[word_count++]);
/* The above always overcounts by one */
word_count -= 1;
if (!strcmp(argm[0], "cd")){
chdir(argm[1]);
} else if (!strcmp(argm[0], "exit")) {
exit(0);
}
}
}
Note my variation on eatWrd(), which does not have to move any data around, and which does not require pre-parsing the string to determine how many words to expect. I suppose your implementation would be more complex, so as to handle quoting or some such, but it could absolutely follow the same general approach.
Note, too, my correction to the command-matching conditions, using !strcmp() instead of strncmp().

Program to remove preceding whitespace

I am working on a program that should remove preceding spaces and tabs from each line of text in a given file (case b). I read the file from stdin, which I got working fine. However I am getting a nasty seg fault that I can't figure out. It happens when I call strcat() in case b. Basically what I was trying to do in case b is iterate through each line (80 characters) in the text file, remove any preceding tabs or spaces from the line, then put these lines back into finalText. Can anyone see where am I going wrong? Or if there might be a simpler approach?
Here's my code:
int main(int argc, char* argv[]) {
int x = 0;
int i = 0;
int j = 0;
int y = 0;
int count = 1;
char *text = malloc(sizeof(char) * 1024);
char *finalText = malloc(sizeof(char) * 1024);
char buff[80];
while(fgets(buff, 80, stdin) != NULL){
strcat(text, buff);
}
while ((x = getopt(argc, argv, "bic:")) != -1){
switch (x){
case 'b':
for(; text[i] != EOF; i += 80){
char buff2[80];
char *buff3;
j = i;
y = 0;
while(j != (80 * count)){
buff2[y] = text[j];
y++;
j++;
}
buff3 = buff2;
while(*buff3 && isspace(*buff3)){
++buff3;
}
count++;
strcat(finalText, buff3);
}
printf(finalText);
break;
default:
break;
}
}
return 0;
}
#include <stdio.h>
int main(){
char buff[80];
int n;
while(fgets(buff, sizeof(buff), stdin)){
sscanf(buff, " %n", &n);
if(n && buff[n-1] == '\n')//only whitespaces line.(nothing first word)
//putchar('\n');//output a newline.
fputs(buff, stdout);//output as itself .
else
fputs(buff + n, stdout);
}
return 0;
}
Firstly before the 'b' case, there is another problem too. You have allocated 1024 byte for text. Each line you read from stdin is concatenated at text string. If the total characters read from stdin exceed 1024 bytes you will receive a segmentation fault.
For your problem at 'b' case:
Why searching for EOF? EOF is not a character and your loop will continue to iterating incrementing i until you receive a segmentation fault. You just want to iterate until the end of the string which can be retrieved with strlen() for example.

Reverse all strings of several files

I need a program to reverse the order of all strings stored in one or more text files. This is what i've got so far:
#include <stdio.h>
main(int argc, char *argv[])
{
int i;
for (i=1;i < argc;i++)
{
FILE *MyFile=fopen(argv[i], "r");
int i,len;
char str[1000], *ptr;
fgets(str, 1000, MyFile);
ptr = str;
for(i=0;i<1000;i++)
{
if(*ptr == '\0') break;
ptr++;
}
len = i;
ptr--;
for(i=len; i>0; i--)
{
printf("%c",*ptr--);
}
printf("\n");
fclose (MyFile);
}
return 0;
}
What i'm not being able to do is to loop the program correctly so that it reverses all strings. Currently it reverses the first string of all files, but when it encounters a line break the fgets stops. What i've tried to do is to count the lines in the current file, do a for loop, and at the end do another fgets(str, 1000, MyFile); to advance the fgets, but I somehow manage to mess things up.
Another option I thought of is to create a separate function which only reverses a given string, and inside the main function call that function the appropriate number of times, but i'm not sure how to handle the argc and *argv[] in this situation.
Any help? Thanks!
You are clobbering the i variable for the outer loop with another one declared inside. This is most probably why it doesn't work.
You should use strlen() function to get the string length instead of calculating it manually.
Unless you are guaranteed to have strings of at most 1000 bytes, you should consider using a smarter algorithm to cater for longer strings.
Accumulate each char in a buffer until end-of-string (\0) detected. Then print it in reverse.
printf_reverse(const char *buf, size_t len) {
while (len > 0) {
fputc(buf[--len], stdout);
}
}
char buf[1000];
size_t len = 0;
int ch;
while ((ch == fgetc(MyFile)) != EOF) {
if (ch == '\0') {
printf_reverse(buf, len);
len = 0;
}
// You may want not use EOL as part of the reverse
else if (ch == '\n') {
printf_reverse(buf, len);
fputc(ch, stdout);
len = 0;
}
else if (len < sizeof(buf)) {
buf[len++] = ch;
}
else {
; // handle error string too long
}
printf_reverse(buf, len);
OP says "ABCD 1234 Should output: DCBA 4321". In C, a string ends with a \0. It is not clear if the source file has embedded \0 or OP also wants to use a space to indicate the end of the string.

Resources