Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #140136 > unrolled thread

Function to trim trailing spaces

Started byDFS <nospam@dfs.com>
First post2019-01-23 21:00 -0500
Last post2019-01-24 03:53 -0800
Articles 20 on this page of 54 — 19 participants

Back to article view | Back to comp.lang.c


Contents

  Function to trim trailing spaces DFS <nospam@dfs.com> - 2019-01-23 21:00 -0500
    Re: Function to trim trailing spaces Joe Pfeiffer <pfeiffer@cs.nmsu.edu> - 2019-01-23 19:14 -0700
      Re: Function to trim trailing spaces DFS <nospam@dfs.com> - 2019-01-23 23:41 -0500
        Re: Function to trim trailing spaces Joe Pfeiffer <pfeiffer@cs.nmsu.edu> - 2019-01-23 22:40 -0700
          Re: Function to trim trailing spaces Bart <bc@freeuk.com> - 2019-01-24 10:44 +0000
          Re: Function to trim trailing spaces DFS <nospam@dfs.com> - 2019-01-24 11:20 -0500
            Re: Function to trim trailing spaces Bart <bc@freeuk.com> - 2019-01-24 16:47 +0000
              Re: Function to trim trailing spaces DFS <nospam@dfs.com> - 2019-01-24 13:51 -0500
            Re: Function to trim trailing spaces Manfred <noname@invalid.add> - 2019-01-24 17:49 +0100
          Re: Function to trim trailing spaces James Kuyper <jameskuyper@alumni.caltech.edu> - 2019-01-24 08:52 -0800
            Re: Function to trim trailing spaces Bart <bc@freeuk.com> - 2019-01-24 17:40 +0000
            Re: Function to trim trailing spaces James Kuyper <jameskuyper@alumni.caltech.edu> - 2019-01-24 12:08 -0800
              Re: Function to trim trailing spaces Joe Pfeiffer <pfeiffer@cs.nmsu.edu> - 2019-01-24 14:47 -0700
                Re: Function to trim trailing spaces scott@slp53.sl.home (Scott Lurndal) - 2019-01-25 14:40 +0000
            Re: Function to trim trailing spaces Joe Pfeiffer <pfeiffer@cs.nmsu.edu> - 2019-01-24 14:44 -0700
        Re: Function to trim trailing spaces Barry Schwarz <schwarzb@dqel.com> - 2019-01-23 23:39 -0800
          Re: Function to trim trailing spaces Rosario19 <Ros@invalid.invalid> - 2019-01-24 10:49 +0100
            Re: Function to trim trailing spaces mark.bluemel@gmail.com - 2019-01-24 01:55 -0800
      Re: Function to trim trailing spaces "Pascal J. Bourguignon" <pjb@informatimago.com> - 2019-01-24 12:58 +0100
      Re: Function to trim trailing spaces Nathan Wagner <nw@hydaspes.if.org> - 2019-01-24 03:01 +0000
    Re: Function to trim trailing spaces Keith Thompson <kst-u@mib.org> - 2019-01-23 18:46 -0800
      Re: Function to trim trailing spaces DFS <nospam@dfs.com> - 2019-01-23 23:38 -0500
        Re: Function to trim trailing spaces Barry Schwarz <schwarzb@dqel.com> - 2019-01-23 23:39 -0800
          Re: Function to trim trailing spaces DFS <nospam@dfs.com> - 2019-01-24 11:25 -0500
            Re: Function to trim trailing spaces mark.bluemel@gmail.com - 2019-01-24 08:34 -0800
            Re: Function to trim trailing spaces Barry Schwarz <schwarzb@dqel.com> - 2019-01-24 15:05 -0800
              Re: Function to trim trailing spaces DFS <nospam@dfs.com> - 2019-01-24 18:40 -0500
        Re: Function to trim trailing spaces Keith Thompson <kst-u@mib.org> - 2019-01-24 02:29 -0800
          Re: Function to trim trailing spaces DFS <nospam@dfs.com> - 2019-01-24 15:06 -0500
            Re: Function to trim trailing spaces Mateusz Viste <mateusz@wont.tell> - 2019-01-24 20:07 +0000
              Re: Function to trim trailing spaces scott@slp53.sl.home (Scott Lurndal) - 2019-01-24 20:24 +0000
                Re: Function to trim trailing spaces Mateusz Viste <mateusz@wont.tell> - 2019-01-24 20:34 +0000
                  Re: Function to trim trailing spaces scott@slp53.sl.home (Scott Lurndal) - 2019-01-24 21:37 +0000
            Re: Function to trim trailing spaces Lew Pitcher <lew.pitcher@digitalfreehold.ca> - 2019-01-24 15:34 -0500
            Re: Function to trim trailing spaces James Kuyper <jameskuyper@alumni.caltech.edu> - 2019-01-24 13:19 -0800
            Re: Function to trim trailing spaces Joe Pfeiffer <pfeiffer@cs.nmsu.edu> - 2019-01-24 14:52 -0700
              Re: Function to trim trailing spaces James Kuyper <jameskuyper@alumni.caltech.edu> - 2019-01-24 14:30 -0800
                Re: Function to trim trailing spaces Joe Pfeiffer <pfeiffer@cs.nmsu.edu> - 2019-01-24 16:59 -0700
            Re: Function to trim trailing spaces Keith Thompson <kst-u@mib.org> - 2019-01-24 14:51 -0800
    Re: Function to trim trailing spaces mark.bluemel@gmail.com - 2019-01-24 01:06 -0800
      Re: Function to trim trailing spaces Keith Thompson <kst-u@mib.org> - 2019-01-24 02:13 -0800
        Re: Function to trim trailing spaces mark.bluemel@gmail.com - 2019-01-24 03:46 -0800
      Re: Function to trim trailing spaces Anton Shepelev <anton.txt@g{oogle}mail.com> - 2019-01-24 14:56 +0300
        Re: Function to trim trailing spaces mark.bluemel@gmail.com - 2019-01-24 05:14 -0800
        Re: Function to trim trailing spaces Ben Bacarisse <ben.usenet@bsb.me.uk> - 2019-01-24 18:51 +0000
          Re: Function to trim trailing spaces "Pascal J. Bourguignon" <pjb@informatimago.com> - 2019-01-24 20:04 +0100
            Re: Function to trim trailing spaces Ben Bacarisse <ben.usenet@bsb.me.uk> - 2019-01-24 20:25 +0000
            Re: Function to trim trailing spaces Anton Shepelev <anton.txt@gmail.com> - 2019-01-24 23:50 +0300
          Re: Function to trim trailing spaces Anton Shepelev <anton.txt@gmail.com> - 2019-01-24 23:45 +0300
            Re: Function to trim trailing spaces Anton Shepelev <anton.txt@gmail.com> - 2019-01-24 23:54 +0300
        Re: Function to trim trailing spaces Ralf Damaschke <rwspam@gmx.de> - 2019-01-24 22:43 +0000
    Re: Function to trim trailing spaces Bart <bc@freeuk.com> - 2019-01-24 10:57 +0000
      Re: Function to trim trailing spaces Bart <bc@freeuk.com> - 2019-01-24 23:05 +0000
    Function to trim trailing spaces "I Set My Girlfriend's Pantyhose on Fire" <cdalten@gmail.com> - 2019-01-24 03:53 -0800

Page 2 of 3 — ← Prev page 1 [2] 3  Next page →


#140138

FromKeith Thompson <kst-u@mib.org>
Date2019-01-23 18:46 -0800
Message-ID<lnef9222nu.fsf@kst-u.example.com>
In reply to#140136
DFS <nospam@dfs.com> writes:
> Needed to right-trim a string (remove trailing spaces), and came up with 
> this:
>
> void rtrim(char * s) {s[strlen(s)-1]='\0';}	
>
>
>
> test_rtrim.c
> ------------------------------------------------
> #include <stdio.h>
>
> void rtrim(char * s) {s[strlen(s)-1]='\0';}	
>
> int main(int argc, char *argv[])
> {
> 	char str[100];	
> 	
> 	printf("\nEnter some text: ");
> 	fgets(str, sizeof(str), stdin);
> 	fseek(stdin,0,SEEK_END);  //flush stdin
> 	
> 	printf("Before: '%s'\n",str);
> 	rtrim(str);
> 	printf("After : '%s'\n",str);
> }
> ------------------------------------------------
>
> Seems to work well.  Any unobvious pitfalls?

No, the pitfalls are fairly obvious.

Joe Pfeiffer already pointed out that your function doesn't do what it's
supposed to do and that you're missing the required `#include <string.h>`.
Testing the function with a string that has several trailing spaces
might have saved some time.

Your fseek call also doesn't do what the comment says it does.  If stdin
is an interactive device (which seems to be the intent), it will simply
fail.  There's no point in "flushing" stdin anyway, since you don't
attempt to read from it again before the program finishes.

And a minor point: The newline before the "Enter some text:" message is
pointless.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Will write code for food.
void Void(void) { Void(); } /* The recursive call of the void */

[toc] | [prev] | [next] | [standalone]


#140139

FromDFS <nospam@dfs.com>
Date2019-01-23 23:38 -0500
Message-ID<Pib2E.185816$JW5.82323@fx46.iad>
In reply to#140138
On 1/23/2019 9:46 PM, Keith Thompson wrote:
> DFS <nospam@dfs.com> writes:
>> Needed to right-trim a string (remove trailing spaces), and came up with
>> this:
>>
>> void rtrim(char * s) {s[strlen(s)-1]='\0';}	
>>
>>
>>
>> test_rtrim.c
>> ------------------------------------------------
>> #include <stdio.h>
>>
>> void rtrim(char * s) {s[strlen(s)-1]='\0';}	
>>
>> int main(int argc, char *argv[])
>> {
>> 	char str[100];	
>> 	
>> 	printf("\nEnter some text: ");
>> 	fgets(str, sizeof(str), stdin);
>> 	fseek(stdin,0,SEEK_END);  //flush stdin
>> 	
>> 	printf("Before: '%s'\n",str);
>> 	rtrim(str);
>> 	printf("After : '%s'\n",str);
>> }
>> ------------------------------------------------
>>
>> Seems to work well.  Any unobvious pitfalls?
> 
> No, the pitfalls are fairly obvious.
> 
> Joe Pfeiffer already pointed out that your function doesn't do what it's
> supposed to do and that you're missing the required `#include <string.h>`.
> Testing the function with a string that has several trailing spaces
> might have saved some time.

I see that now.

Seems I got "lucky", but what I want is correct.  Hence the post.


> Your fseek call also doesn't do what the comment says it does.  If stdin
> is an interactive device (which seems to be the intent), it will simply
> fail.  

It doesn't fail at all, but yes, I know it's not a true flush of stdin.

This snippet is from a larger program, where I keyboard prompt 3x 
consecutively.

Without the "flush" after the 1st prompt, the code falls through to the 
3rd prompt without letting you enter anything for the 2nd prompt.

Without the "flush" after the 2nd prompt, the 3rd prompts fails (falls 
through without letting you enter anything).

So I do those flushes after all 3 prompts and it works fine.


> There's no point in "flushing" stdin anyway, since you don't
> attempt to read from it again before the program finishes.

Yeah, it wasn't necessary for this demo.


> And a minor point: The newline before the "Enter some text:" message is
> pointless.

Thanks for the reply.


[toc] | [prev] | [next] | [standalone]


#140143

FromBarry Schwarz <schwarzb@dqel.com>
Date2019-01-23 23:39 -0800
Message-ID<i9qi4etluacag0ki0f11ldd1bljgm5n1q2@4ax.com>
In reply to#140139
On Wed, 23 Jan 2019 23:38:26 -0500, DFS <nospam@dfs.com> wrote:

>On 1/23/2019 9:46 PM, Keith Thompson wrote:
>> DFS <nospam@dfs.com> writes:
>>> Needed to right-trim a string (remove trailing spaces), and came up with
>>> this:
>>>
>>> void rtrim(char * s) {s[strlen(s)-1]='\0';}	
>>>
>>>
>>>
>>> test_rtrim.c
>>> ------------------------------------------------
>>> #include <stdio.h>
>>>
>>> void rtrim(char * s) {s[strlen(s)-1]='\0';}	
>>>
>>> int main(int argc, char *argv[])
>>> {
>>> 	char str[100];	
>>> 	
>>> 	printf("\nEnter some text: ");
>>> 	fgets(str, sizeof(str), stdin);
>>> 	fseek(stdin,0,SEEK_END);  //flush stdin
>>> 	
>>> 	printf("Before: '%s'\n",str);
>>> 	rtrim(str);
>>> 	printf("After : '%s'\n",str);
>>> }
>>> ------------------------------------------------
>>>
>>> Seems to work well.  Any unobvious pitfalls?
>> 
>> No, the pitfalls are fairly obvious.
>> 
>> Joe Pfeiffer already pointed out that your function doesn't do what it's
>> supposed to do and that you're missing the required `#include <string.h>`.
>> Testing the function with a string that has several trailing spaces
>> might have saved some time.
>
>I see that now.
>
>Seems I got "lucky", but what I want is correct.  Hence the post.
>
>
>> Your fseek call also doesn't do what the comment says it does.  If stdin
>> is an interactive device (which seems to be the intent), it will simply
>> fail.  
>
>It doesn't fail at all, but yes, I know it's not a true flush of stdin.
>
>This snippet is from a larger program, where I keyboard prompt 3x 
>consecutively.
>
>Without the "flush" after the 1st prompt, the code falls through to the 
>3rd prompt without letting you enter anything for the 2nd prompt.

That is usually caused by residual data in the buffer, in particular
the result of pressing Enter.  How are you reading the input?

>Without the "flush" after the 2nd prompt, the 3rd prompts fails (falls 
>through without letting you enter anything).

What data do you enter in response to the first prompt?

>So I do those flushes after all 3 prompts and it works fine.

Right up until you show the program to your customer, port the program
to a different machine, or apply some update to your OS or run-time
library.

-- 
Remove del for email

[toc] | [prev] | [next] | [standalone]


#140169

FromDFS <nospam@dfs.com>
Date2019-01-24 11:25 -0500
Message-ID<fDl2E.55962$Rk4.15294@fx32.iad>
In reply to#140143
On 1/24/2019 2:39 AM, Barry Schwarz wrote:
> On Wed, 23 Jan 2019 23:38:26 -0500, DFS <nospam@dfs.com> wrote:
> 
>> On 1/23/2019 9:46 PM, Keith Thompson wrote:
>>> DFS <nospam@dfs.com> writes:
>>>> Needed to right-trim a string (remove trailing spaces), and came up with
>>>> this:
>>>>
>>>> void rtrim(char * s) {s[strlen(s)-1]='\0';}	
>>>>
>>>>
>>>>
>>>> test_rtrim.c
>>>> ------------------------------------------------
>>>> #include <stdio.h>
>>>>
>>>> void rtrim(char * s) {s[strlen(s)-1]='\0';}	
>>>>
>>>> int main(int argc, char *argv[])
>>>> {
>>>> 	char str[100];	
>>>> 	
>>>> 	printf("\nEnter some text: ");
>>>> 	fgets(str, sizeof(str), stdin);
>>>> 	fseek(stdin,0,SEEK_END);  //flush stdin
>>>> 	
>>>> 	printf("Before: '%s'\n",str);
>>>> 	rtrim(str);
>>>> 	printf("After : '%s'\n",str);
>>>> }
>>>> ------------------------------------------------
>>>>
>>>> Seems to work well.  Any unobvious pitfalls?
>>>
>>> No, the pitfalls are fairly obvious.
>>>
>>> Joe Pfeiffer already pointed out that your function doesn't do what it's
>>> supposed to do and that you're missing the required `#include <string.h>`.
>>> Testing the function with a string that has several trailing spaces
>>> might have saved some time.
>>
>> I see that now.
>>
>> Seems I got "lucky", but what I want is correct.  Hence the post.
>>
>>
>>> Your fseek call also doesn't do what the comment says it does.  If stdin
>>> is an interactive device (which seems to be the intent), it will simply
>>> fail.
>>
>> It doesn't fail at all, but yes, I know it's not a true flush of stdin.
>>
>> This snippet is from a larger program, where I keyboard prompt 3x
>> consecutively.
>>
>> Without the "flush" after the 1st prompt, the code falls through to the
>> 3rd prompt without letting you enter anything for the 2nd prompt.
> 
> That is usually caused by residual data in the buffer, in particular
> the result of pressing Enter.  How are you reading the input?

Enter a number, then hit Enter


>> Without the "flush" after the 2nd prompt, the 3rd prompts fails (falls
>> through without letting you enter anything).
> 
> What data do you enter in response to the first prompt?


1st prompt: enter a number    getchar()
2nd prompt: enter a number    getchar()
3rd prompt: enter a filename  fgets()

[toc] | [prev] | [next] | [standalone]


#140170

Frommark.bluemel@gmail.com
Date2019-01-24 08:34 -0800
Message-ID<a9a243db-b921-4955-b7c1-6484d65d04fd@googlegroups.com>
In reply to#140169
On Thursday, 24 January 2019 16:22:44 UTC, DFS  wrote:

> 
> 1st prompt: enter a number    getchar()
> 2nd prompt: enter a number    getchar()
> 3rd prompt: enter a filename  fgets()

I suggest reading and understanding the topics covered in
<http://c-faq.com/stdio/index.html>. 
Terminal input in C isn't necessarily easy and mixing different calls
without a clear understanding is a recipe for problems. fflush()ing
is not necessarily a solution, even if it helps in this case.

[toc] | [prev] | [next] | [standalone]


#140214

FromBarry Schwarz <schwarzb@dqel.com>
Date2019-01-24 15:05 -0800
Message-ID<pigk4e967s1jgrgnn9al2pd633bb45g9j4@4ax.com>
In reply to#140169
On Thu, 24 Jan 2019 11:25:18 -0500, DFS <nospam@dfs.com> wrote:

>On 1/24/2019 2:39 AM, Barry Schwarz wrote:
>> On Wed, 23 Jan 2019 23:38:26 -0500, DFS <nospam@dfs.com> wrote:
>> 
>>> On 1/23/2019 9:46 PM, Keith Thompson wrote:
>>>> DFS <nospam@dfs.com> writes:
>>>>> Needed to right-trim a string (remove trailing spaces), and came up with
>>>>> this:
>>>>>
>>>>> void rtrim(char * s) {s[strlen(s)-1]='\0';}	
>>>>>
>>>>>
>>>>>
>>>>> test_rtrim.c
>>>>> ------------------------------------------------
>>>>> #include <stdio.h>
>>>>>
>>>>> void rtrim(char * s) {s[strlen(s)-1]='\0';}	
>>>>>
>>>>> int main(int argc, char *argv[])
>>>>> {
>>>>> 	char str[100];	
>>>>> 	
>>>>> 	printf("\nEnter some text: ");
>>>>> 	fgets(str, sizeof(str), stdin);
>>>>> 	fseek(stdin,0,SEEK_END);  //flush stdin
>>>>> 	
>>>>> 	printf("Before: '%s'\n",str);
>>>>> 	rtrim(str);
>>>>> 	printf("After : '%s'\n",str);
>>>>> }
>>>>> ------------------------------------------------
>>>>>
>>>>> Seems to work well.  Any unobvious pitfalls?
>>>>
>>>> No, the pitfalls are fairly obvious.
>>>>
>>>> Joe Pfeiffer already pointed out that your function doesn't do what it's
>>>> supposed to do and that you're missing the required `#include <string.h>`.
>>>> Testing the function with a string that has several trailing spaces
>>>> might have saved some time.
>>>
>>> I see that now.
>>>
>>> Seems I got "lucky", but what I want is correct.  Hence the post.
>>>
>>>
>>>> Your fseek call also doesn't do what the comment says it does.  If stdin
>>>> is an interactive device (which seems to be the intent), it will simply
>>>> fail.
>>>
>>> It doesn't fail at all, but yes, I know it's not a true flush of stdin.
>>>
>>> This snippet is from a larger program, where I keyboard prompt 3x
>>> consecutively.
>>>
>>> Without the "flush" after the 1st prompt, the code falls through to the
>>> 3rd prompt without letting you enter anything for the 2nd prompt.
>> 
>> That is usually caused by residual data in the buffer, in particular
>> the result of pressing Enter.  How are you reading the input?
>
>Enter a number, then hit Enter
>
>
>>> Without the "flush" after the 2nd prompt, the 3rd prompts fails (falls
>>> through without letting you enter anything).
>> 
>> What data do you enter in response to the first prompt?
>
>
>1st prompt: enter a number    getchar()
>2nd prompt: enter a number    getchar()
>3rd prompt: enter a filename  fgets()

Since getchar extracts a single character from the buffer, can we
assume that you are entering single digit values?

If so, you type in one digit (let's assume '1') and then you press
Enter.  The buffer now contains two characters, '1' and '\n'.  getchar
extracts the '1' and leaves the '\n' in the buffer.  You print the
next prompt and call getchar again (expecting it to wait for more
input).  However, getchar is quite willing to extract the '\n' and
return it to your program.  Since getchar has returned, your program
happily moves on to the third prompt.

The two most common portable methods of avoiding this problem are:
   1 - Call getchar after obtaining the data you want but ignore the
return value.  But this will not help in this case if the user types
in two digits.
   2 - Extract the input into a string using fgets (which will extract
the \n also) and convert it to the numeric form you need using either
sscanf or one the strto... functions.  This is the preferred method if
you want to perform validity checks after extracting the data.

-- 
Remove del for email

[toc] | [prev] | [next] | [standalone]


#140218

FromDFS <nospam@dfs.com>
Date2019-01-24 18:40 -0500
Message-ID<U%r2E.35655$q54.2702@fx15.iad>
In reply to#140214
On 1/24/2019 6:05 PM, Barry Schwarz wrote:
> On Thu, 24 Jan 2019 11:25:18 -0500, DFS <nospam@dfs.com> wrote:
> 
>> On 1/24/2019 2:39 AM, Barry Schwarz wrote:
>>> On Wed, 23 Jan 2019 23:38:26 -0500, DFS <nospam@dfs.com> wrote:
>>>
>>>> On 1/23/2019 9:46 PM, Keith Thompson wrote:
>>>>> DFS <nospam@dfs.com> writes:
>>>>>> Needed to right-trim a string (remove trailing spaces), and came up with
>>>>>> this:
>>>>>>
>>>>>> void rtrim(char * s) {s[strlen(s)-1]='\0';}	
>>>>>>
>>>>>>
>>>>>>
>>>>>> test_rtrim.c
>>>>>> ------------------------------------------------
>>>>>> #include <stdio.h>
>>>>>>
>>>>>> void rtrim(char * s) {s[strlen(s)-1]='\0';}	
>>>>>>
>>>>>> int main(int argc, char *argv[])
>>>>>> {
>>>>>> 	char str[100];	
>>>>>> 	
>>>>>> 	printf("\nEnter some text: ");
>>>>>> 	fgets(str, sizeof(str), stdin);
>>>>>> 	fseek(stdin,0,SEEK_END);  //flush stdin
>>>>>> 	
>>>>>> 	printf("Before: '%s'\n",str);
>>>>>> 	rtrim(str);
>>>>>> 	printf("After : '%s'\n",str);
>>>>>> }
>>>>>> ------------------------------------------------
>>>>>>
>>>>>> Seems to work well.  Any unobvious pitfalls?
>>>>>
>>>>> No, the pitfalls are fairly obvious.
>>>>>
>>>>> Joe Pfeiffer already pointed out that your function doesn't do what it's
>>>>> supposed to do and that you're missing the required `#include <string.h>`.
>>>>> Testing the function with a string that has several trailing spaces
>>>>> might have saved some time.
>>>>
>>>> I see that now.
>>>>
>>>> Seems I got "lucky", but what I want is correct.  Hence the post.
>>>>
>>>>
>>>>> Your fseek call also doesn't do what the comment says it does.  If stdin
>>>>> is an interactive device (which seems to be the intent), it will simply
>>>>> fail.
>>>>
>>>> It doesn't fail at all, but yes, I know it's not a true flush of stdin.
>>>>
>>>> This snippet is from a larger program, where I keyboard prompt 3x
>>>> consecutively.
>>>>
>>>> Without the "flush" after the 1st prompt, the code falls through to the
>>>> 3rd prompt without letting you enter anything for the 2nd prompt.
>>>
>>> That is usually caused by residual data in the buffer, in particular
>>> the result of pressing Enter.  How are you reading the input?
>>
>> Enter a number, then hit Enter
>>
>>
>>>> Without the "flush" after the 2nd prompt, the 3rd prompts fails (falls
>>>> through without letting you enter anything).
>>>
>>> What data do you enter in response to the first prompt?
>>
>>
>> 1st prompt: enter a number    getchar()
>> 2nd prompt: enter a number    getchar()
>> 3rd prompt: enter a filename  fgets()
> 
> Since getchar extracts a single character from the buffer, can we
> assume that you are entering single digit values?

Yes.  1 or 2 (sometimes also 3 or 4).

Currently no validation on the entered value.


> If so, you type in one digit (let's assume '1') and then you press
> Enter.  The buffer now contains two characters, '1' and '\n'.  getchar
> extracts the '1' and leaves the '\n' in the buffer.  You print the
> next prompt and call getchar again (expecting it to wait for more
> input).  However, getchar is quite willing to extract the '\n' and
> return it to your program.  Since getchar has returned, your program
> happily moves on to the third prompt.
> 
> The two most common portable methods of avoiding this problem are:
>     1 - Call getchar after obtaining the data you want but ignore the
> return value.  But this will not help in this case if the user types
> in two digits.
>     2 - Extract the input into a string using fgets (which will extract
> the \n also) and convert it to the numeric form you need using either
> sscanf or one the strto... functions.  This is the preferred method if
> you want to perform validity checks after extracting the data.

Good answer.  Thanks.

[toc] | [prev] | [next] | [standalone]


#140150

FromKeith Thompson <kst-u@mib.org>
Date2019-01-24 02:29 -0800
Message-ID<ln1s521h8v.fsf@kst-u.example.com>
In reply to#140139
DFS <nospam@dfs.com> writes:
> On 1/23/2019 9:46 PM, Keith Thompson wrote:
>> DFS <nospam@dfs.com> writes:
>>> Needed to right-trim a string (remove trailing spaces), and came up with
>>> this:
>>>
>>> void rtrim(char * s) {s[strlen(s)-1]='\0';}	
>>>
>>> test_rtrim.c
>>> ------------------------------------------------
>>> #include <stdio.h>
>>>
>>> void rtrim(char * s) {s[strlen(s)-1]='\0';}	
>>>
>>> int main(int argc, char *argv[])
>>> {
>>> 	char str[100];	
>>> 	
>>> 	printf("\nEnter some text: ");
>>> 	fgets(str, sizeof(str), stdin);
>>> 	fseek(stdin,0,SEEK_END);  //flush stdin
>>> 	
>>> 	printf("Before: '%s'\n",str);
>>> 	rtrim(str);
>>> 	printf("After : '%s'\n",str);
>>> }
>>> ------------------------------------------------
>>>
>>> Seems to work well.  Any unobvious pitfalls?
[...]
>> Your fseek call also doesn't do what the comment says it does.  If stdin
>> is an interactive device (which seems to be the intent), it will simply
>> fail.  
>
> It doesn't fail at all, but yes, I know it's not a true flush of stdin.

In the program you posted, you can't tell whether it fails because you
don't test the result.

> This snippet is from a larger program, where I keyboard prompt 3x
> consecutively.
>
> Without the "flush" after the 1st prompt, the code falls through to
> the 3rd prompt without letting you enter anything for the 2nd prompt.
>
> Without the "flush" after the 2nd prompt, the 3rd prompts fails (falls
> through without letting you enter anything).
>
> So I do those flushes after all 3 prompts and it works fine.

That's odd.  Since you talk about keyboard prompts, I presume
that stdin is associated with a keyboard.  I would have expected
fseek(stdin, ...)  to fail in that case.

Can you show a (possibly reduced version of) your program in which it
works as you say it does?

I just did a test.  On Ubuntu Linux, using the above program, fseek()
fails and sets errno to 29 (ESPIPE, Illegal seek).  On Windows
(compiling with x86_64-w64-mingw32-gcc) the fseek() call succeeds,
but I'm not sure what it does.

If you want to discard input (for example, all characters up to and
including the next newline), it's probably better to read and discard
them

    int c; do c = getchar(); while (c != EOF && c != '\n');

rather than playing tricks with fseek().  (It's not necessary in your
small example because fgets() has already read the newline -- assuming
the input line isn't too long.)

[...]

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Will write code for food.
void Void(void) { Void(); } /* The recursive call of the void */

[toc] | [prev] | [next] | [standalone]


#140188

FromDFS <nospam@dfs.com>
Date2019-01-24 15:06 -0500
Message-ID<pTo2E.115832$Fj3.56469@fx06.iad>
In reply to#140150
On 1/24/2019 5:29 AM, Keith Thompson wrote:
> DFS <nospam@dfs.com> writes:
>> On 1/23/2019 9:46 PM, Keith Thompson wrote:
>>> DFS <nospam@dfs.com> writes:
>>>> Needed to right-trim a string (remove trailing spaces), and came up with
>>>> this:
>>>>
>>>> void rtrim(char * s) {s[strlen(s)-1]='\0';}	
>>>>
>>>> test_rtrim.c
>>>> ------------------------------------------------
>>>> #include <stdio.h>
>>>>
>>>> void rtrim(char * s) {s[strlen(s)-1]='\0';}	
>>>>
>>>> int main(int argc, char *argv[])
>>>> {
>>>> 	char str[100];	
>>>> 	
>>>> 	printf("\nEnter some text: ");
>>>> 	fgets(str, sizeof(str), stdin);
>>>> 	fseek(stdin,0,SEEK_END);  //flush stdin
>>>> 	
>>>> 	printf("Before: '%s'\n",str);
>>>> 	rtrim(str);
>>>> 	printf("After : '%s'\n",str);
>>>> }
>>>> ------------------------------------------------
>>>>
>>>> Seems to work well.  Any unobvious pitfalls?
> [...]
>>> Your fseek call also doesn't do what the comment says it does.  If stdin
>>> is an interactive device (which seems to be the intent), it will simply
>>> fail.
>>
>> It doesn't fail at all, but yes, I know it's not a true flush of stdin.
> 
> In the program you posted, you can't tell whether it fails because you
> don't test the result.


How could   fseek(stdin,0,SEEK_END);   ever fail?




>> This snippet is from a larger program, where I keyboard prompt 3x
>> consecutively.
>>
>> Without the "flush" after the 1st prompt, the code falls through to
>> the 3rd prompt without letting you enter anything for the 2nd prompt.
>>
>> Without the "flush" after the 2nd prompt, the 3rd prompts fails (falls
>> through without letting you enter anything).
>>
>> So I do those flushes after all 3 prompts and it works fine.
> 
> That's odd.  Since you talk about keyboard prompts, I presume
> that stdin is associated with a keyboard.  I would have expected
> fseek(stdin, ...)  to fail in that case.
> 
> Can you show a (possibly reduced version of) your program in which it
> works as you say it does?


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void rtrim(char * s) {s[strlen(s)-1]='\0';}	

/*
above is the original rtrim(), subject of this thread.  I've since 
replaced it with:

void rtrim(char * s)
{
     int i=0, index=0;
     while(s[i] != '\0')
     {
         if(s[i]!=' ' && s[i]!='\t' && s[i]!='\n') {index= i;}
         i++;
     }
     s[index+1]='\0';
}	
*/


int main(int argc, char *argv[])
{	

	//vars
	char fileop[8];
	char separator[2];
	char filein[100];
	int i;
	FILE *fin;
	
	//get values from keyboard
	fseek(stdin,0,SEEK_END);

	printf("Choose file operation:\n1. Summary\n2. Data Operations\n");
	i = getchar();
	memset(fileop, '\0', sizeof(fileop));
	if (i=='1') {strcpy(fileop,"summary");}
	if (i=='2') {strcpy(fileop,"data");}
	fseek(stdin,0,SEEK_END);
		
	printf("\nChoose field separator:\n");
	printf("1. pipe  |\n2. pound #\n3. tilde ~\n4. comma ,\n");
	i = getchar();
	memset(separator, '\0', 2);
	if (i=='1') {strcpy(separator,"|");}
	if (i=='2') {strcpy(separator,"#");}
	if (i=='3') {strcpy(separator,"~");}
	if (i=='4') {strcpy(separator,",");}
	fseek(stdin,0,SEEK_END);

	printf("\nEnter name of .csv file:\n");
	fgets(filein, sizeof(filein), stdin);
	rtrim(filein);
	fseek(stdin,0,SEEK_END);


//that's all 3 keyboard prompts.  After this I open the .csv "filein", 
count headers and data rows, print the results, then close the file and exit

}




> I just did a test.  On Ubuntu Linux, using the above program, fseek()
> fails and sets errno to 29 (ESPIPE, Illegal seek).  On Windows
> (compiling with x86_64-w64-mingw32-gcc) the fseek() call succeeds,
> but I'm not sure what it does.
> 
> If you want to discard input (for example, all characters up to and
> including the next newline), it's probably better to read and discard
> them
> 
>      int c; do c = getchar(); while (c != EOF && c != '\n');
> 
> rather than playing tricks with fseek().  (It's not necessary in your
> small example because fgets() has already read the newline -- assuming
> the input line isn't too long.)
> 
> [...]


FYI: tcc 0.9.26 on Windows

$tcc -Wall csvmgr.c -o csvmgr.exe

compiles with no warnings

[toc] | [prev] | [next] | [standalone]


#140190

FromMateusz Viste <mateusz@wont.tell>
Date2019-01-24 20:07 +0000
Message-ID<5c4a1af5$0$3539$426a74cc@news.free.fr>
In reply to#140188
On Thu, 24 Jan 2019 15:06:29 -0500, DFS wrote:
>> In the program you posted, you can't tell whether it fails because you
>> don't test the result.
> 
> How could   fseek(stdin,0,SEEK_END);   ever fail?

It could fail if you closed stdin. That's something daemons commonly do.

Mateusz

[toc] | [prev] | [next] | [standalone]


#140194

Fromscott@slp53.sl.home (Scott Lurndal)
Date2019-01-24 20:24 +0000
Message-ID<1ap2E.215322$Z45.42723@fx44.iad>
In reply to#140190
Mateusz Viste <mateusz@wont.tell> writes:
>On Thu, 24 Jan 2019 15:06:29 -0500, DFS wrote:
>>> In the program you posted, you can't tell whether it fails because you
>>> don't test the result.
>> 
>> How could   fseek(stdin,0,SEEK_END);   ever fail?
>
>It could fail if you closed stdin. That's something daemons commonly do.

Most demons will re-open "/dev/null" on fd0.

[toc] | [prev] | [next] | [standalone]


#140197

FromMateusz Viste <mateusz@wont.tell>
Date2019-01-24 20:34 +0000
Message-ID<5c4a2152$0$20331$426a74cc@news.free.fr>
In reply to#140194
On Thu, 24 Jan 2019 20:24:29 +0000, Scott Lurndal wrote:
> Mateusz Viste <mateusz@wont.tell> writes:
>>On Thu, 24 Jan 2019 15:06:29 -0500, DFS wrote:
>>>> In the program you posted, you can't tell whether it fails because
>>>> you don't test the result.
>>> 
>>> How could   fseek(stdin,0,SEEK_END);   ever fail?
>>
>>It could fail if you closed stdin. That's something daemons commonly do.
> 
> Most demons will re-open "/dev/null" on fd0.

This only means that fseek() would "mostly work". Is that good enough? I 
think it is not.

Mateusz

[toc] | [prev] | [next] | [standalone]


#140205

Fromscott@slp53.sl.home (Scott Lurndal)
Date2019-01-24 21:37 +0000
Message-ID<Teq2E.86129$375.28604@fx40.iad>
In reply to#140197
Mateusz Viste <mateusz@wont.tell> writes:
>On Thu, 24 Jan 2019 20:24:29 +0000, Scott Lurndal wrote:
>> Mateusz Viste <mateusz@wont.tell> writes:
>>>On Thu, 24 Jan 2019 15:06:29 -0500, DFS wrote:
>>>>> In the program you posted, you can't tell whether it fails because
>>>>> you don't test the result.
>>>> 
>>>> How could   fseek(stdin,0,SEEK_END);   ever fail?
>>>
>>>It could fail if you closed stdin. That's something daemons commonly do.
>> 
>> Most demons will re-open "/dev/null" on fd0.
>
>This only means that fseek() would "mostly work". Is that good enough? I 
>think it is not.

I dunno.  In over forty years of C and Posix programming, I've never
needed to use fseek(3) at all.    seek(2) and later lseek(2) yes, fseek(3) never.  But then,
I typically avoid stdio for most real world usage scenarios; favoring mmap()
or pread(2)/pwrite(2) for most cases.

[toc] | [prev] | [next] | [standalone]


#140196

FromLew Pitcher <lew.pitcher@digitalfreehold.ca>
Date2019-01-24 15:34 -0500
Message-ID<q2d7fq$s9f$1@dont-email.me>
In reply to#140188
DFS wrote:

> On 1/24/2019 5:29 AM, Keith Thompson wrote:
>> DFS <nospam@dfs.com> writes:
>>> On 1/23/2019 9:46 PM, Keith Thompson wrote:
>>>> DFS <nospam@dfs.com> writes:
>>>>> Needed to right-trim a string (remove trailing spaces), and came up
>>>>> with this:
>>>>>
>>>>> void rtrim(char * s) {s[strlen(s)-1]='\0';}
>>>>>
>>>>> test_rtrim.c
>>>>> ------------------------------------------------
>>>>> #include <stdio.h>
>>>>>
>>>>> void rtrim(char * s) {s[strlen(s)-1]='\0';}
>>>>>
>>>>> int main(int argc, char *argv[])
>>>>> {
>>>>> char str[100];
>>>>> 
>>>>> printf("\nEnter some text: ");
>>>>> fgets(str, sizeof(str), stdin);
>>>>> fseek(stdin,0,SEEK_END);  //flush stdin
>>>>> 
>>>>> printf("Before: '%s'\n",str);
>>>>> rtrim(str);
>>>>> printf("After : '%s'\n",str);
>>>>> }
>>>>> ------------------------------------------------
>>>>>
>>>>> Seems to work well.  Any unobvious pitfalls?
>> [...]
>>>> Your fseek call also doesn't do what the comment says it does.  If
>>>> stdin is an interactive device (which seems to be the intent), it will
>>>> simply fail.
>>>
>>> It doesn't fail at all, but yes, I know it's not a true flush of stdin.
>> 
>> In the program you posted, you can't tell whether it fails because you
>> don't test the result.
> 
> 
> How could   fseek(stdin,0,SEEK_END);   ever fail?

C11:
  7.21.9.2 The fseek function
  Synopsis
  1 #include <stdio.h>

  int fseek(FILE *stream, long int offset, int whence);

  Description
  2 The fseek function sets the file position indicator for the stream
    pointed to by stream.
  ...
  Returns
  6 The fseek function returns nonzero only for a request that cannot be
    satisfied.


One implementation:

  NAME
       fgetpos, fseek, fsetpos, ftell, rewind - reposition a stream

  SYNOPSIS
       #include <stdio.h>

       int fseek(FILE *stream, long offset, int whence);

  DESCRIPTION
       The  fseek()  function  sets the file position indicator for the
       stream pointed to by stream.
       ...
  ERRORS
       EBADF  The stream specified is not a seekable stream.


>>> This snippet is from a larger program, where I keyboard prompt 3x
>>> consecutively.
>>>
>>> Without the "flush" after the 1st prompt, the code falls through to
>>> the 3rd prompt without letting you enter anything for the 2nd prompt.
>>>
>>> Without the "flush" after the 2nd prompt, the 3rd prompts fails (falls
>>> through without letting you enter anything).
>>>
>>> So I do those flushes after all 3 prompts and it works fine.
>> 
>> That's odd.  Since you talk about keyboard prompts, I presume
>> that stdin is associated with a keyboard.  I would have expected
>> fseek(stdin, ...)  to fail in that case.
>> 
>> Can you show a (possibly reduced version of) your program in which it
>> works as you say it does?
> 
> 
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
> 
> void rtrim(char * s) {s[strlen(s)-1]='\0';}
> 
> /*
> above is the original rtrim(), subject of this thread.  I've since
> replaced it with:
> 
> void rtrim(char * s)
> {
>      int i=0, index=0;
>      while(s[i] != '\0')
>      {
>          if(s[i]!=' ' && s[i]!='\t' && s[i]!='\n') {index= i;}
>          i++;
>      }
>      s[index+1]='\0';
> }
> */
> 
> 
> int main(int argc, char *argv[])
> {
> 
> //vars
> char fileop[8];
> char separator[2];
> char filein[100];
> int i;
> FILE *fin;
> 
> //get values from keyboard
> fseek(stdin,0,SEEK_END);
> 
> printf("Choose file operation:\n1. Summary\n2. Data Operations\n");
> i = getchar();
> memset(fileop, '\0', sizeof(fileop));
> if (i=='1') {strcpy(fileop,"summary");}
> if (i=='2') {strcpy(fileop,"data");}
> fseek(stdin,0,SEEK_END);
> 
> printf("\nChoose field separator:\n");
> printf("1. pipe  |\n2. pound #\n3. tilde ~\n4. comma ,\n");
> i = getchar();
> memset(separator, '\0', 2);
> if (i=='1') {strcpy(separator,"|");}
> if (i=='2') {strcpy(separator,"#");}
> if (i=='3') {strcpy(separator,"~");}
> if (i=='4') {strcpy(separator,",");}
> fseek(stdin,0,SEEK_END);
> 
> printf("\nEnter name of .csv file:\n");
> fgets(filein, sizeof(filein), stdin);
> rtrim(filein);
> fseek(stdin,0,SEEK_END);
> 
> 
> //that's all 3 keyboard prompts.  After this I open the .csv "filein",
> count headers and data rows, print the results, then close the file and
> exit
> 
> }
> 
> 
> 
> 
>> I just did a test.  On Ubuntu Linux, using the above program, fseek()
>> fails and sets errno to 29 (ESPIPE, Illegal seek).  On Windows
>> (compiling with x86_64-w64-mingw32-gcc) the fseek() call succeeds,
>> but I'm not sure what it does.
>> 
>> If you want to discard input (for example, all characters up to and
>> including the next newline), it's probably better to read and discard
>> them
>> 
>>      int c; do c = getchar(); while (c != EOF && c != '\n');
>> 
>> rather than playing tricks with fseek().  (It's not necessary in your
>> small example because fgets() has already read the newline -- assuming
>> the input line isn't too long.)
>> 
>> [...]
> 
> 
> FYI: tcc 0.9.26 on Windows
> 
> $tcc -Wall csvmgr.c -o csvmgr.exe
> 
> compiles with no warnings


-- 
Lew Pitcher
"In Skills, We Trust"

[toc] | [prev] | [next] | [standalone]


#140202

FromJames Kuyper <jameskuyper@alumni.caltech.edu>
Date2019-01-24 13:19 -0800
Message-ID<05292e40-78d7-4964-8d1c-ffad7d8eb041@googlegroups.com>
In reply to#140188
On Thursday, January 24, 2019 at 3:04:46 PM UTC-5, DFS wrote:
> On 1/24/2019 5:29 AM, Keith Thompson wrote:
> > DFS <nospam@dfs.com> writes:
> >> On 1/23/2019 9:46 PM, Keith Thompson wrote:
> >>> DFS <nospam@dfs.com> writes:
> >>>> Needed to right-trim a string (remove trailing spaces), and came up with
> >>>> this:
> >>>>
> >>>> void rtrim(char * s) {s[strlen(s)-1]='\0';}	
> >>>>
> >>>> test_rtrim.c
> >>>> ------------------------------------------------
> >>>> #include <stdio.h>
> >>>>
> >>>> void rtrim(char * s) {s[strlen(s)-1]='\0';}	
> >>>>
> >>>> int main(int argc, char *argv[])
> >>>> {
> >>>> 	char str[100];	
> >>>> 	
> >>>> 	printf("\nEnter some text: ");
> >>>> 	fgets(str, sizeof(str), stdin);
> >>>> 	fseek(stdin,0,SEEK_END);  //flush stdin
> >>>> 	
> >>>> 	printf("Before: '%s'\n",str);
> >>>> 	rtrim(str);
> >>>> 	printf("After : '%s'\n",str);
> >>>> }
> >>>> ------------------------------------------------
> >>>>
> >>>> Seems to work well.  Any unobvious pitfalls?
> > [...]
> >>> Your fseek call also doesn't do what the comment says it does.  If stdin
> >>> is an interactive device (which seems to be the intent), it will simply
> >>> fail.
> >>
> >> It doesn't fail at all, but yes, I know it's not a true flush of stdin.
> > 
> > In the program you posted, you can't tell whether it fails because you
> > don't test the result.
> 
> 
> How could   fseek(stdin,0,SEEK_END);   ever fail?


Footnote 268 says "Setting the file position indicator to end-of-file,
as with fseek(file, 0, SEEK_END), has undefined behavior for a binary
stream (because of possible trailing null characters) or for any stream
with state-dependent encoding that does not assuredly end in the initial
shift state."

"A binary stream need not meaningfully support fseek calls with a whence
value of SEEK_END." (7.21.9.2p3).

For example, The Open Group Base Specifications Issue 7, 2018 edition
IEEE Std 1003.1-2017 (Revision of IEEE Std 1003.1-2008) lists the
following possible reasons for the above call to fseek() to fail:

"    [ESPIPE]
        [CX] The file descriptor underlying stream is associated with a
pipe, FIFO, or socket.

    The fseek() ...  functions may fail if:

    [ENXIO]
        [CX] A request was made of a nonexistent device, or the request
was outside the capabilities of the device."

[toc] | [prev] | [next] | [standalone]


#140208

FromJoe Pfeiffer <pfeiffer@cs.nmsu.edu>
Date2019-01-24 14:52 -0700
Message-ID<1b5zud4tac.fsf@pfeifferfamily.net>
In reply to#140188
DFS <nospam@dfs.com> writes:
>
> How could   fseek(stdin,0,SEEK_END);   ever fail?

From the man page:

ERRORS
       EINVAL The whence argument to fseek() was not SEEK_SET, SEEK_END, or  SEEK_CUR.   Or:  the
              resulting file offset would be negative.

       ESPIPE The  file  descriptor underlying stream is not seekable (e.g., it refers to a pipe,
              FIFO, or socket).

See the second case.

[toc] | [prev] | [next] | [standalone]


#140209

FromJames Kuyper <jameskuyper@alumni.caltech.edu>
Date2019-01-24 14:30 -0800
Message-ID<ccea22f8-fadf-41f4-baed-47e427886734@googlegroups.com>
In reply to#140208
On Thursday, January 24, 2019 at 4:53:07 PM UTC-5, Joe Pfeiffer wrote:
> DFS <nospam@dfs.com> writes:
> >
> > How could   fseek(stdin,0,SEEK_END);   ever fail?
> 
> From the man page:
> 
> ERRORS
>        EINVAL The whence argument to fseek() was not SEEK_SET, SEEK_END, or  SEEK_CUR.

The whence argument is SEEK_END.

   Or:  the
>               resulting file offset would be negative.

How could the file offset for fseek(file, 0, SEEK_END) be negative?

[toc] | [prev] | [next] | [standalone]


#140219

FromJoe Pfeiffer <pfeiffer@cs.nmsu.edu>
Date2019-01-24 16:59 -0700
Message-ID<1b1s514nfx.fsf@pfeifferfamily.net>
In reply to#140209
James Kuyper <jameskuyper@alumni.caltech.edu> writes:

> On Thursday, January 24, 2019 at 4:53:07 PM UTC-5, Joe Pfeiffer wrote:
>> DFS <nospam@dfs.com> writes:
>> >
>> > How could   fseek(stdin,0,SEEK_END);   ever fail?
>> 
>> From the man page:
>> 
>> ERRORS
>>        EINVAL The whence argument to fseek() was not SEEK_SET, SEEK_END, or  SEEK_CUR.
>
> The whence argument is SEEK_END.
>
>    Or:  the
>>               resulting file offset would be negative.
>
> How could the file offset for fseek(file, 0, SEEK_END) be negative?


I was referring to

       ESPIPE The  file  descriptor underlying stream is not seekable (e.g., it refers to a pipe,
              FIFO, or socket).

as the second case.

[toc] | [prev] | [next] | [standalone]


#140212

FromKeith Thompson <kst-u@mib.org>
Date2019-01-24 14:51 -0800
Message-ID<lnwomtzn1u.fsf@kst-u.example.com>
In reply to#140188
DFS <nospam@dfs.com> writes:
[...]
> How could   fseek(stdin,0,SEEK_END);   ever fail?

On my system (Ubuntu), it consistently fails, returning -1 and
setting errno to ESPIPE (Illegal seek) -- because stdin is not
a seekable stream when it's connected to the keyboard.  (I'm not
entirely sure what that fseek is supposed to do.)

I tried your latest program (see the parent of this article) on
Windows, compiling with x86_64-w64-mingw32-gcc.exe under Cygwin. The
fseek() calls succeed, but I don't see the initial prompt.

If you've read a partial line of input, as you've done with your
first getchar() call, the portable way to discard the rest of the
line is to read characters until you encounter a newline or EOF.

[...]

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Will write code for food.
void Void(void) { Void(); } /* The recursive call of the void */

[toc] | [prev] | [next] | [standalone]


#140144

Frommark.bluemel@gmail.com
Date2019-01-24 01:06 -0800
Message-ID<549145a8-950f-4027-9495-b909ab34a6a9@googlegroups.com>
In reply to#140136
On Thursday, 24 January 2019 01:59:58 UTC, DFS  wrote:
> Needed to right-trim a string (remove trailing spaces), and came up with 
> this:
> 
> void rtrim(char * s) {s[strlen(s)-1]='\0';}	
> 
> 
> 
> test_rtrim.c
> ------------------------------------------------
> #include <stdio.h>
> 
> void rtrim(char * s) {s[strlen(s)-1]='\0';}	
> 
> int main(int argc, char *argv[])
> {
> 	char str[100];	
> 	
> 	printf("\nEnter some text: ");
> 	fgets(str, sizeof(str), stdin);
> 	fseek(stdin,0,SEEK_END);  //flush stdin
> 	
> 	printf("Before: '%s'\n",str);
> 	rtrim(str);
> 	printf("After : '%s'\n",str);
> }
> ------------------------------------------------
> 
> Seems to work well.  Any unobvious pitfalls?

As already mentioned, there are enough obvious ones to
be going on with.

If ever there was an example of the need for Test
Driven Development, this looks like it - not because 
the task is hard, but because programmers need to be
made to think.

Please tell us what happens when you run the following
snippets.

  char *s = "my dog has fleas";
  printf("Before: '%s'\n",str);
  rtrim(str);
  printf("After : '%s'\n",str);

On some platforms/compilers, it's quite likely to fail dramatically as 
string constants are read-only. If it doesn't in your environment, that's
down to (bad) luck.

  char *s = strdup("my dog has fleas");
  printf("Before: '%s'\n",str);
  rtrim(str);
  printf("After : '%s'\n",str);

  char *s = strdup("my dog has fleas        ");
  printf("Before: '%s'\n",str);
  rtrim(str);
  printf("After : '%s'\n",str);

  char *s = strdup("       ");
  printf("Before: '%s'\n",str);
  rtrim(str);
  printf("After : '%s'\n",str);

  char *s = strdup(" ");
  printf("Before: '%s'\n",str);
  rtrim(str);
  printf("After : '%s'\n",str);

Did that do what you really wanted?

Here's my 10-minute simplistic hack to do the job.
The rtrim() function is not elegant, but suffices, and my main
point is to show some basic ideas about how you could use testing.
(My more complete example would test the results against expected
values).

#include <string.h>
#include <stdio.h>
#include <stdlib.h>

char *rtrim(char *str) {
  char * result = strdup(str);
  int i = strlen(result);
  for (i = i-1; i >= 0 && result[i]==' '; i--) {
    result[i] = 0;
  }
  return result;
}

int main(void) {

  char * testStrings[] = {
    "my dog has no spaces",
    "my dog has one space ",
    "my dog has lots of spaces               ",
    " ",
    "    "
  };

  int i;

  for (i = 0; i < sizeof(testStrings)/sizeof(testStrings[0]); i++) {
    char *trimmed = rtrim(testStrings[i]);
    printf("before '%s' after '%s'\n", testStrings[i], trimmed);
    free(trimmed);
  }

}

[toc] | [prev] | [next] | [standalone]


Page 2 of 3 — ← Prev page 1 [2] 3  Next page →

Back to top | Article view | comp.lang.c


csiph-web