putc to print string to word in separate line C - c

i wanna print string to each word in each line .it looks like putc not working and why i can not use putchar in c programming language ?
#include <stdio.h>
#include <conio.h>
#include <string.h>
void main() {
char s[50];
int i, len;
printf("\enter string : ");
gets(s);
len = strlen(s);
i = 0;
while (i<len) {
while (s[i] == ' ' && i<len)
i++;
while (s[i] != ' ' && i<len)
putc(s[i++], stdout);
putc('\n', stdout);
}
getch();
}

There's nothing massively wrong with your code, other than:
the use of non-standard features like conio.h and getch;
the use of unsafe functions (which tend not to matter in classwork that much);
the wrong order for conditions in your while statements, which may cause undefined behaviour.
Hence, this code appears to do what you need:
#include <stdio.h>
#include <string.h>
int main (void) {
char s[50];
int i, len;
printf("enter string : ");
gets(s);
len = strlen(s);
i = 0;
while (i<len) {
while (i < len && s[i] == ' ')
i++;
while (i < len && s[i] != ' ')
putc(s[i++], stdout);
putc('\n', stdout);
}
return 0;
}
However, it's not that clean, a professional coder would tend to opt for more modularisation and worthwhile comments, something along the lines of the following. First, some general functions for skipping spaces and echoing words:
#include <stdio.h>
#include <string.h>
static char *skipSpaces (char *pStr) {
// Just throw away spaces, returning address of first non-space.
while (*pStr == ' ')
pStr++;
return pStr;
}
static char *echoWord (char *pStr) {
// If at end of string, say so.
if (*pStr == '\0')
return NULL;
// Echo the word itself.
while ((*pStr != '\0') && (*pStr != ' '))
putchar (*pStr++);
// Then skip to start of next word (or end of string).
pStr = skipSpaces (pStr);
// Return new pointer.
return pStr;
}
Then, with that done, the main program becomes a lot easier to understand:
int main (void) {
// Get string from user in a more safe manner.
char str[50];
printf("Enter string: ");
fgets (str, sizeof (str), stdin);
// Remove newline if there.
size_t len = strlen (str);
if ((len > 0) && (str[len-1] == '\n'))
str[len-1] = '\0';
// Start with first real character.
char *pStr = skipSpaces (str);
// Process words and space groups (adding newline) until at end of string.
while ((pStr = echoWord (pStr)) != NULL)
putchar ('\n');
return 0;
}

Related

reading and saving known number of lines of unknown lengths of strings

I want to receive the number of lines of input from the user then read and save the lines of unknown lengths in an array.
I know that the way I am saving the lines is wrong but I don't know how to correct it.
int nos; // number of strings
scanf_s("%d", &nos);
char** strs = malloc(nos * sizeof(char*)); // array of strings
for (int i = 0; i < nos; i++) // receiving strings
{
scanf_s("%s", (strs+i));
}
You're close, but you're forgetting to allocate memory for the string. If you're working with POSIX-compliant systems (i.e. pretty much everything except Windows) then use the %ms scanf() format specifier to allocate the buffer for the string as you're reading it (note that this stops after whitespace):
scanf("%ms", &strs[i]);
For Windows, implement a gets()-like function:
#include <stdlib.h>
#include <stdio.h>
int msgets(char **str)
{
int ch = 0;
size_t len = 0;
while(ch != '\n')
{
len++;
*str = realloc(*str, len);
ch = getchar();
(*str)[len-1] = ch;
}
(*str)[--len] = 0;
return len;
}
Here's how to use it in replacement of the scanf() line:
msgets(&strs[i]);
Other than that, your code looks fine.
Here's an almost complete example with my code included:
#include <stdlib.h>
#include <stdio.h>
int msgets(char **str)
{
int ch = 0;
size_t len = 0;
while(ch != '\n')
{
len++;
*str = realloc(*str, len);
ch = getchar();
(*str)[len-1] = ch;
}
(*str)[--len] = 0;
return len;
}
int main(void)
{
int nos; // number of strings
scanf("%d ", &nos);
char** strs = malloc(nos * sizeof(char*)); // array of strings
for (int i = 0; i < nos; i++) // receiving strings
{
msgets(&strs[i]);
}
/* Do something with strs[] here */
return 0;
}
if you read carefully this answerHow can I read an input string of unknown length? , and modify your code it should be something like this.
I also add a print for loop to see the results of this code
#include <stdio.h>
#include <stdlib.h>
char *inputString(FILE* fp, size_t size){
char *str=NULL;
int ch;
size_t len = 0;
str = realloc(str, sizeof(char)*size);
if(!str){
printf("[DEBUG]\n");
return str;
}
while(EOF!=(ch=fgetc(fp)) && ch != '\n'){
str[len++]=ch;
if(len==size){
str = realloc(str, sizeof(char)*(size+=16));
if(!str)return str;
}
}
str[len++]='\0';
return realloc(str, sizeof(char)*len);
}
void empty_stdin (void) /* simple helper-function to empty stdin */
{
char c;
while ((c = getchar()) != '\n' && c != EOF);
return;
}
int main(void){
int nos,i; /*number of strings*/
scanf("%d", &nos);
empty_stdin();
char ** strs = malloc(nos * sizeof(char*)); /*array of strings*/
for (i = 0; i < nos; i++) {/*receiving strings*/
*(strs+i) = inputString(stdin,1);
}
for(i=0;i<nos;i++){
printf("%s\n",*(strs+i));
}
return 0;
}
input:
3
123456789
foo
hello world
output:
123456789
foo
hello world

Converting from arrays to pointers. Am I missing something?

I had to rewrite two functions as per two exercises in a book I'm working from. One that simply reads a line of characters, readLine and another that compared two character strings and returned either 1 or 0 based on whether they match, 'equalStrings`.
The point of the exercise was to rewrite the functions so they used pointers, as opposed to arrays.
I've been struggling with prior exercises and was surprised how quickly I was able to do this so I'm concerned I'm missing something important.
Both programs compile and run as hoped though.
This is the original readLine function:
#include <stdio.h>
void readLine(char buffer[]);
int main(void)
{
int i;
char line[81];
for(i = 0; i < 3; i++)
{
readLine(line);
printf("%s\n\n", line);
}
return 0;
}
void readLine(char buffer[])
{
char character;
int i = 0;
do
{
character = getchar();
buffer[i] = character;
i++;
}
while(character != '\n');
buffer[i - 1] = '\0';
}
My edited with pointers:
#include <stdio.h>
void readLine(char *buffer);
int main(void)
{
int i;
char line[81];
char *pointer;
pointer = line;
for(i = 0; i < 3; i++)
{
readLine(pointer);
printf("%s\n\n", line);
}
return 0;
}
void readLine(char *buffer)
{
char character;
int i;
i = 0;
do
{
character = getchar();
buffer[i] = character;
i++;
}
while(character != '\n');
buffer[i - 1] = '\0';
}
Here is the original equalString function:
#include <stdio.h>
#include <stdbool.h>
bool equalStrings(const char s1[], const char s2[]);
int main(void)
{
const char stra[] = "string compare test";
const char strb[] = "string";
printf("%i\n", equalStrings(stra, strb));
printf("%i\n", equalStrings(stra, stra));
printf("%i\n", equalStrings(strb, "string"));
return 0;
}
bool equalStrings(const char s1[], const char s2[])
{
int i = 0;
bool areEqual;
while(s1[i] == s2[i] && s1[i] != '\0'){
i++;
if(s1[i] == '\0' && s2[i] == '\0')
areEqual = true;
else
areEqual = false;
}
return areEqual;
}
and the rewritten with pointers:
#include <stdio.h>
#include <stdbool.h>
bool equalStrings(const char *pointera, const char *pointerb);
int main(void)
{
const char stra[] = "string compare test";
const char strb[] = "string";
const char *pointera;
const char *pointerb;
pointera = stra;
pointerb = strb;
printf("%i\n", equalStrings(pointera, pointerb));
printf("%i\n", equalStrings(pointerb, pointerb));
printf("%i\n", equalStrings(strb, "string"));
return 0;
}
bool equalStrings(const char *pointera, const char *pointerb)
{
int i = 0;
bool areEqual;
while(pointera[i] == pointerb[i] && pointera[i] != '\0'){
i++;
if(pointera[i] == '\0' && pointerb[i] == '\0')
areEqual = true;
else
areEqual = false;
}
return areEqual;
}
Is there anything glaring out that needs to be changed?
Thank you.
There are (3) conditions you need to protect against in your readline function. (1) you must protect against writing beyond the end of your array. Utilizing a simple counter to keep track of the number of characters added will suffice. You can express this limit in your read loop. Your array size is 81 (which will hold a string of 80 characters +1 for the nul-terminating character. Assuming you create a #define MAXC 81 for use in your code, your first condition could be written as:
void readline (char *buffer)
{
int i = 0, c;
while (i + 1 < MAXC && ...
(2) the second condition you want to protect against is reaching a '\n' newline character. The second condition for your read loop could be written as:
while (i + 1 < MAXC && (c = getchar()) != '\n' && ...
(3) the third condition you must protect against is encountering EOF with a line before a newline character is reached (many editors produce files with non-POSIX line-endings). With the final condition, your complete set of test conditions could look like the following:
while (i + 1 < MAXC && (c = getchar()) != '\n' && c != EOF)
(and that is why c must be signed (and should be a signed int), because EOF is generally -1)
Putting that together, with what it appears was intended in rewriting the function from using array-index notation to using pointer notation, you could do something like the following:
void readline (char *buffer)
{
int i = 0, c;
while (i + 1 < MAXC && (c = getchar()) != '\n' && c != EOF) {
*buffer++ = c;
i++;
}
*buffer = 0;
if (i + 1 == MAXC && *(buffer - 1) != '\n')
fprintf (stderr, "warning: line truncation occurred.\n");
}
You should also check, as shown above, whether you read all the characters in the line, or whether a short-read occurred (meaning after reading 80 allowable characters, there were still more characters in the line to be read, but to prevent writing beyond the end of your array, and leaving room for the terminating nul, you stopped reading before your reached the newline). You are free to handle it as you like, but be aware -- those characters still exist in the input buffer (stdin here) and will be the very next characters read on your next call to getchar(). So you may want a way to tell if that occurred.
Putting the function together in a short example with a helpful input file will help explain.
#include <stdio.h>
#define MAXC 81
void readline(char *buffer);
int main(void) {
int i;
char line[MAXC] = "", *pointer = line;
for(i = 0; i < 3; i++) {
readline (pointer);
printf ("%s\n\n", line);
}
return 0;
}
void readline (char *buffer)
{
int i = 0, c;
while (i + 1 < MAXC && (c = getchar()) != '\n' && c != EOF) {
*buffer++ = c;
i++;
}
*buffer = 0;
if (i + 1 == MAXC && *(buffer - 1) != '\n')
fprintf (stderr, "warning: line truncation occurred.\n");
}
How will your function behave if given a 90 character line to read?
Input File
Two lines with 90 characters each.
$cat dat/90.txt
123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
Example Use/Output
Note what has occurred. On the first read attempt, 80 character were read, and a short read occurred. You were warned of that fact. The second read, read the reamining 10 characters in the first line (chars 81-90). The third, and final, read, again reads the first 80 chars of the second line and the code terminates.
$ ./bin/getchar_ptr <dat/90.txt
warning: line truncation occurred.
12345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890
warning: line truncation occurred.
12345678901234567890123456789012345678901234567890123456789012345678901234567890
I'll let you look this over and incorporate any of the suggestions you find helpul in the rest of your code. Let me know if you have any questions. Make sure you fully undetstand what is being passed as buffer in void readline (char *buffer) (copy as opposed to original) as basic pointer understandin has implications throughout C.

strcat is giving me a segmentation fault error

After verifying that strcat is where the error occurs, I then check the previous example in my assignment. In my previous examples I use strcat(actually strncat) in the same fashion as I do for my following code. I am not too sure.
The purpose of my program is to loop through "string" and remove any occurances the character 'c' from string.
main.c:
char string[100]={0}, c[3];
printf("Enter a String: ");
fgets(string, 100, stdin);
if (string[98] == '\n' && string[99] == '\0') { while ( (ch = fgetc(stdin)) != EOF && ch != '\n'); }
printf("Enter a Char: ");
fgets(c, 2, stdin);
while ( (ch = fgetc(stdin)) != EOF && ch != '\n');
rmchr(string, c[0]);
header:
rmchr(char *string, char c)
{
int i=0;
char *word[100];
int s = strlen(string);
for(i=0; i<=(s-2); i++)
{
if(string[i] != c)
{
strcat(word, string[i]);
}
}
}
char *word[100];
It will hold a string in your program so use:
char word[100];
that is, an array of char instead of an array of char *.
Then strcat concatenates to a string but word is not initialized. Make it a string with:
word[0] = '\0';
Then string[i] is a character but strcat needs pointers to character arguments: to use a pointer use &string[i].
Finally the problem in your rmchr function is it has to return something, either through the arguments or via a return statement but it doesn't.
There are more than one point to mention here, like
rmchr() definition should have a return type, maybe void if you're not returning anything.
[FWIW, In that case, I wounder, how you'll make use of the local variable word]
inside rmchr(), word needs to be an array of chars, not char pointers. You need to change char * word[100] to char word[100].
In strcat(), both the arguments, needs to be a pointer. You need to use &string[i], in that case.
The following seems to compile fine but your code doesnt do quite what you said you wanted, "The purpose of my program is to loop through "string" and remove any occurances the character 'c' from string.". the function doesn't remove the character or return a copy of the string with the character excluded. I wrote a function that copies the string after removing the character and returns pointer to it. below is your code a bit modified and under it is my function
//Just a compilable version of your code, not sure if it does what u want
#include <stdio.h>
#include <string.h>
void rmchr(char *string, char c)
{
int i=0;
char word[100];
int s = (int)strlen(string);
for(i=0; i<=(s-2); i++)
{
if(string[i] != c)
{
strcat(word, (char *)(&string[i]));
}
}
}
int main(int argc, const char * argv[]) {
char string[100] = {0}, c[3];
char ch;
printf("Enter a String: ");
fgets(string, 100, stdin);
if (string[98] == '\n' && string[99] == '\0') {
while ( (ch = fgetc(stdin)) != EOF && ch != '\n');
}
printf("Enter a Char: ");
fgets(c, 2, stdin);
while ( (ch = fgetc(stdin)) != EOF && ch != '\n');
rmchr(string, c[0]);
return 0;
}
There you go, with a demo main
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* rmchr(char *string, char ch)
{
int counter = 0;
int new_size = 0;
char corrected_string[100];
while (string[counter] != '\n' && string[counter] != '\0' && string[counter] != EOF) {
if (string[counter] != ch) {
corrected_string[new_size] = string[counter];
new_size++;
}
counter++;
}
char *new_string = (char *)malloc((new_size+1) * sizeof(char));
for (int j = 0; j <= new_size; j++) {
new_string[j] = corrected_string[j];
}
return new_string;
}
int main(int argc, const char * argv[]) {
char *s = "The char 'c' will be removed";
char *new = rmchr(s, 'c');
printf("%s", new);
return 0;
}

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().

How do I replace multiple spaces with a single space?

Well I'm looking for a function that reduce multiple space characters ' ' in a string.
For example for string s given :
s="hello__________world____!"
The function must return "hello_world_!"
In python we can do it via regexp simply as:
re.sub("\s+", " ", s);
A version that modifies the string in place, run it on a copy if the original must be preserved:
void compress_spaces(char *str)
{
char *dst = str;
for (; *str; ++str) {
*dst++ = *str;
if (isspace(*str)) {
do ++str;
while (isspace(*str));
--str;
}
}
*dst = 0;
}
There is no such function in the C standard library. One must write a function to do so or use a third-party library.
The following function should do the trick. Use the source string as the destination pointer to perform the operation in place. Otherwise, ensure that the destination buffer is sufficiently sized.
void
simplifyWhitespace(char * dst, const char * src)
{
for (; *src; ++dst, ++src) {
*dst = *src;
if (isspace(*src))
while (isspace(*(src + 1)))
++src;
}
*dst = '\0';
}
void remove_more_than_one_space(char *dest, char *src)
{
int i, y;
assert(dest && src);
for(i=0, y=0; src[i] != '\0'; i++, y++) {
if(src[i] == ' ' && src[i+1] == ' ') {
/* let's skip this copy and reduce the y index*/
y--;
continue;
}
/* copy normally */
dest[y] = src[i];
}
dest[y] = '\0';
}
int main()
{
char src[] = "Hello World ! !! !";
char dest[strlen(src) + 1];
remove_more_than_one_space(dest, src);
printf("%s\n", dest);
}
I just made this, hope it helps.
#include<stdio.h>
#include<string.h>
#include<ctype.h>
int main()
{
char word[100];
gets(word);
//the word has more than a single space in between the words
int i=0,l,j;
l=strlen(word);
for (i=0;i<l;i++)
{
if(word[i]==' '&&word[i+1]==' ')
{
for(j=i+1;j<l;j++)
word[j]=word[j+1];
}
}
puts(word);
return 0;
}
This code is very simple and it worked like a charm for me. I don't know if this code will have some other problems I haven't come across, but for now this works.
I'm just learning C, so I'm using much more basic code. I'm reading the first chapter of "The C programming language", and I was trying to find the answer to a task set in there.
This is what I came up with:
#include <stdio.h>
int main()
{
/* Set two integers:
c is the character being assessed,
lastspace is 1 if the lastcharacter was a space*/
int c, lastspace;
lastspace = 0;
/* This while loop will exit if the character is EOF
The first "If block" is true if the character is not a space,
and just prints the character
It also tells us that the lastcharacter was not a space
The else block will run if the character is a space
Then the second IF block will run if the last character
was not also a space (and will print just one space) */
while((c = getchar()) != EOF){
if (c != ' '){
putchar(c);
lastspace = 0;
}
else {
if (lastspace != 1)
putchar(c);
lastspace = 1;
}
}
return 0;
}
Hope that helps!
Also, I am well aware that this code is perhaps not optimised, but it should be simple for a beginner like me to understand!
Thanks, Phil
another way of doing this to print only the first occurrence of space until next character comes, here is my brute force solution.
#include<stdio.h>
typedef int bool;
#define True 1
#define False 0
int main()
{
int t;
bool flag = False;
while ((t = getchar()) != EOF)
if (t == ' ' && !flag)
{
putchar(' ');
flag = True; // flag is true for the first occurence of space
}
else if(t == ' '&& flag)
continue;
else
{
putchar(t);
flag = False;
}
return 0;
}
hope it helps.

Resources