0

I am new to C programming. I am taking a class where I have to:

The program will take all input from standard input, possibly transform it, and output it to standard output.

The program will read in input line by line. Transformations, if any, will be done per line. Then print out the transformed line.

You will have to read from the user until there is no more text left. Ctrl+D can be typed into the terminal to indicate there is no text left.

I am not a student who is looking for the answer to be done for me, but I am completely lost here. I tried to use:

char*buf = NULL;
while (fscanf(stdin, "%ms", &buf) > 0)
{ do transform } 

but I have no luck. So any help is appreciated. Also I have no idea about the Ctrl+D part.

Community
  • 1
  • 1
tTIKA
  • 73
  • 1
  • 10

3 Answers3

4
char*buf = NULL;
while (fscanf(stdin, "%ms", &buf) > 0)

has the following problems.

  1. buf does not point to anything valid where input can be read and stored.
  2. %ms is not a standard C format specifier (it is supported in POSIX standard compliant platforms, thanks @JonathanLeffler).
  3. It will be better to use fgets to read lines of text.

I sugguest:

// Make LINE_LENGTH large enough for your needs.
#define LINE_LENGTH 200
char buf[LINE_LENGTH]; 
while ( fgets(buf, LINE_LENGTH, stdin) != NULL )
{
   // Use buf
}
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • 1
    `%ms` is standard — the standard is POSIX (IEEE 1003.1:2008) rather than ISO/IEC 9899:2011. See [`fscanf()`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fscanf.html) for the details. – Jonathan Leffler May 28 '17 at 05:54
  • is there a way to make this work with an unwon line size (or trim out the char array size at the end)? – tTIKA May 28 '17 at 05:54
  • @tTIKA, making it work with an unknown line size is possible but will make your code complex. I don't understand what you meant about trimming out the char array. – R Sahu May 28 '17 at 06:01
  • You'll need to note in due course that `%s` (with or without the `m` modifier) doesn't read lines. – Jonathan Leffler May 28 '17 at 06:02
  • @CoolGuy, it is moot if the OP continues to use `%ms`. – R Sahu May 28 '17 at 06:57
2

Ctrl+D is EOF usually so just check for that. fscanf(stdin, "%ms", &buf)!=EOF

Also you reserved just a pointer to char, you should either statically reserve array or do dynamic allocation. char buf[255]; or char *buf = (char*) malloc(255);

EDIT: As noted by Jonathan Leffler fscanf() is really terrible idea if your lines don't have specific format use fgets() https://www.tutorialspoint.com/c_standard_library/c_function_fgets.htm

dage5
  • 96
  • 1
  • 5
  • 1
    Note that `%ms` is a POSIX extension for [`fscanf()`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fscanf.html) compared with standard C. It dynamically allocates the correct memory when passed a `char **`. – Jonathan Leffler May 28 '17 at 05:50
  • @dage5 thanks for the help. But do you think this will work for the question? How would I access each line severely in but? – tTIKA May 28 '17 at 05:52
  • @JonathanLeffler can you elaborate on that a bit. Also, should I use scans or fscanf? – tTIKA May 28 '17 at 05:53
  • Well line is in `buf` array. – dage5 May 28 '17 at 05:54
  • @dage5 will it put all the lines just next to each other? – tTIKA May 28 '17 at 05:56
  • @tTIKA: What do you need elaborated? The specification is in the link. It is clear. If you don't understand the features you are using, maybe you shouldn't be using them. You must check the return value from `fscanf()`. IMO, the approach using `scanf()` to read 'lines' is wholly mistaken. By default, `scanf()` et al could not care the slightest about lines. You have to work very hard to make them care. Since you don't show the `do transform` code, we can't tell what you're doing wrong. However, if that does not include `free(buf);` near the end of the loop, you're leaking memory. – Jonathan Leffler May 28 '17 at 05:56
  • @tTIKA: You should be using either standard C [`fgets()`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fgets.html) or POSIX [`getline()`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getline.html) to read the lines. – Jonathan Leffler May 28 '17 at 05:58
  • @tTIKA No it will put one line at a time into `buf`. – dage5 May 28 '17 at 06:00
  • 1
    @dage5: No, it won't put one line at a time. Using `scanf()` and `%s` skips an arbitrary amount of white space (zero or more blanks, tabs, newlines, etc) and then reads one word, terminated by the next white space character. That's why I've added that `scanf()` et al are the wrong functions to use to read 'lines'. – Jonathan Leffler May 28 '17 at 06:02
  • @Jonathan Leffler Yeah that is right I shouldnt be answering questions in the morning. Sorry, fscanf is good only for formatted input(like for eaxmple many lines in format of a string number string) and you should use fgets(). – dage5 May 28 '17 at 06:05
1

Since you tagged as C++, try this:

std::string text;
std::getline(cin, text);

The std::string will dynamically expand as necessary.

The getline function will read until an end-of-line character is read.

Much safer than reading into a character array.

Thomas Matthews
  • 56,849
  • 17
  • 98
  • 154