I am currently trying to learn C by using the K&R, but I am completely stumped by example 1.5.2. For some reason, after I press Ctrl-Z, instead of printing nc, it prints nc multiplied by 2. I don't know what could be causing this problem (I copied the code exactly how it is in the book). The compiler I am using is Visual Studio 2010. Here is the code:
#include <stdio.h>
main()
{
long nc;
nc = 0;
while (getchar() != EOF)
++nc;
printf("%1d\n", nc);
}
Because enter is a keystroke.
If your input is:
1<enter>
1<enter>
1<enter>
^z
it would output:
6
Not sure why you get the behaviour you describe but that should be %ld not %1d
Could not reproduce your error. I added some debugging statements,
#include <stdio.h>
main() {
int nc = 0, ch;
while ((ch = getchar()) != EOF) {
printf("%d\n", ch);
++nc;
}
printf("nc - %1d\n", nc);
}
And then tried it with gcc on Windows:
E:\temp>gcc eof.c
E:\temp>a
^Z
nc - 0
E:\temp>a
foo bar
102
111
111
32
98
97
114
10
^Z
nc - 8
And then with Visual Studio 2008:
E:\temp>cl eof.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.
eof.c
Microsoft (R) Incremental Linker Version 9.00.30729.01
Copyright (C) Microsoft Corporation. All rights reserved.
/out:eof.exe
eof.obj
E:\temp>eof
^Z
nc - 0
E:\temp>eof
foo bar
102
111
111
32
98
97
114
10
^Z
nc - 8
Related
I am learning c++ and the excersise involves opening a .txt file and reading from it.
The project structure is as following:
int main()
{
static const char* full_name = "C:\Users\Lukas\Desktop\Programming\file_system_test\file_system_test\items.txt";
FILE* my_file = fopen(full_name , "r");
if (my_file == NULL) {
perror("error opening file");
}
}
I am trying to fopen items.txt but with no luck yet..
I am not exactly sure what is the problem since I provide the full path..
METHODS TRIED SO FAR:
Using double backslash in full path
static const char* full_name = "C:\\Users\\Lukas\Desktop\\Programming\\file_system_test\\file_system_test\\items.txt";
Error still persists with:
error opening file: No such file or directory
SOLVED
The only thing that seems to fix this code is to use raw string literal as following:
static const char* full_name3 = R"(C:/Users/Lukas/Desktop/Programming/file_system_test/file_system_test/items.txt)";
FILE* my_file3 = fopen(full_name3, "r");
if (my_file3 == NULL) {
perror("error opening file");
}
Does not return any errors anymore.
Note escape sequences of string literals, so your path:
static const char* full_name = "C:\Users\Lukas\Desktop\Programming\file_system_test\file_system_test\items.txt";
contains \f escape sequence which is interpreted as form feed - new page byte 0x0c in ASCII encoding. This character can't be part of of a path so Invalid argument error is reported.
Also compilers complain that other escape sequences are unknown.
There are three ways to fix it.
As Luka Rahne suggested by using back slash escape sequence \\
Or by using forward slashes (since C suppose to be portable, standard library is able to convert Unix path separator to platform specific path separators).
static const char* full_name = "C:/Users/Lukas/Desktop/Programming/file_system_test/file_system_test/items.txt";
If you are using C++11 or newer (your code is C not C++, but tag says C++), you can leverage raw string literal:
static const char* full_name = R"(C:\Users\Lukas\Desktop\Programming\file_system_test\file_system_test\items.txt)";
Here I did some live testing with msvc (file named: open.c):
#include <stdlib.h>
#include <stdio.h>
int main(int argc, const char argv[])
{
#if VERSION == 0
// here '\f' is used to reproduce error "invalid argument":
static const char name[] = "C:\fUsers\\User\\Downloads\\open.c";
#elif VERSION == 1
static const char name[] = "C:\\Users\\User\\Downloads\\open.c";
#elif VERSION == 2
static const char name[] = "C:/Users/User/Downloads/open.c";
#elif VERSION == 3
static const char name[] = R"(C:\Users\User\Downloads\open.c)";
#endif
FILE* f = fopen(name, "r");
if (!f) {
perror("fopen");
return 1;
}
char buf[256] = "";
fgets(buf, sizeof(buf), f);
printf("%s\n", buf);
fclose(f);
return 0;
}
Here is result of compiling and running from cmd.exe:
C:\Users\User\Downloads>cl open.c /D VERSION=0 && open.exe
Microsoft (R) C/C++ Optimizing Compiler Version 19.28.29336 for x86
Copyright (C) Microsoft Corporation. All rights reserved.
open.c
Microsoft (R) Incremental Linker Version 14.28.29336.0
Copyright (C) Microsoft Corporation. All rights reserved.
/out:open.exe
open.obj
fopen: Invalid argument
C:\Users\User\Downloads>cl open.c /D VERSION=1 && open.exe
Microsoft (R) C/C++ Optimizing Compiler Version 19.28.29336 for x86
Copyright (C) Microsoft Corporation. All rights reserved.
open.c
Microsoft (R) Incremental Linker Version 14.28.29336.0
Copyright (C) Microsoft Corporation. All rights reserved.
/out:open.exe
open.obj
#include <stdlib.h>
C:\Users\User\Downloads>cl open.c /D VERSION=2 && open.exe
Microsoft (R) C/C++ Optimizing Compiler Version 19.28.29336 for x86
Copyright (C) Microsoft Corporation. All rights reserved.
open.c
Microsoft (R) Incremental Linker Version 14.28.29336.0
Copyright (C) Microsoft Corporation. All rights reserved.
/out:open.exe
open.obj
#include <stdlib.h>
C:\Users\User\Downloads>cl open.c /D VERSION=3 && open.exe
Microsoft (R) C/C++ Optimizing Compiler Version 19.28.29336 for x86
Copyright (C) Microsoft Corporation. All rights reserved.
open.c
open.c(11): warning C4129: 'm': unrecognized character escape sequence
open.c(11): warning C4129: 'D': unrecognized character escape sequence
open.c(11): warning C4129: 'o': unrecognized character escape sequence
open.c(11): error C2065: 'R': undeclared identifier
open.c(11): error C2143: syntax error: missing ';' before 'string'
open.c(11): error C2099: initializer is not a constant
So everything works as I described and last version 3 fails since I compile code as C.
I believe your issue is that \ in filename is not properly escaped.
Your filename string should have double backslash characters.
static const char* full_name = "C:\\Users\\Lukas\\Desktop\\Programming\\file_system_test\\file_system_test\\items.txt";
You can test this, by sending this string trough std::cout for debug.
I started learning C programming with C Programming Language by Denis M Ritchie I am trying to execute program from that book
#include <stdio.h>
/* count lines in input */
main()
{
int c, nl;
nl = 0;
while ((c = getchar()) != EOF)
if (c == '\n')
++nl;
printf("%d\n", nl);
getchar();
}
However all I get is blank console and when I type text and press enter,no value is displayed.
I am using Visual Studio 2013 IDE.
The program you posted here is for counting number of lines.
Q. However all I get is blank console and when I type text and press
enter,no value is displayed
A. Yes it shows nothing because while ((c = getchar()) != EOF) waits until you enter EOF (use ctrl + z then you will get number for lines).
getchar(c);
See declaration of getchar.
int getchar(void)
It doesn't take any parameter. Didn't it gave you error.
And main should be int main.
There are several issues. First, main has to have a type, usually int
- main()
+ int main()
and your program should return an exit status
Secondly getchar takes no arguments, and returns the input
http://www.tutorialspoint.com/c_standard_library/c_function_getchar.htm
- getchar(c)
+ c = getchar()
You can compile your program by calling
gcc -Wall test.c -o test
Where test.c is your code, and test is the binary. -Wall will show all the "warning" (errors that don't interfere with the program execution)
I believe that you use Windows, it's better to add:
system("pause");
Moreover to use system("pause"), only in Windows, you need to include another library:
#include <stdlib.h>
You can see your results but the problem here, is that you have an infinite loop. Yo need to check the \n, count and when you have a specific number, you leave from the loop.
I'm completely new to C, and I am attempting to run this example code on xcode, but it says build failed. I got the code exact like it is in the book, but it still won't run.
#include <stdio.h>
/* count characters in input; 2nd version */
int main()
{
double nc;
for (nc =0; getchar() != EOF; ++nc) {
;
}
printf("%.0f\n", nc);
}
Sorry if it's a noob question. All help is appreciated!
The question code lacks a 'return {int value}' statement. I added this missing line, and ended up with the following code:
#include <stdio.h>
/* count characters in input; 2nd version */
int main()
{
double nc;
for (nc =0; getchar() != EOF; ++nc) {
;
}
printf("%.0f\n", nc);
return(0);
}
The above compiled without errors or warnings using:
gcc -Wall -o test test.c
To run it requires that input to the program comes from a file.
I made a file named 'junk.txt' with the following content (not including the braces):
[ adddsadsd 33334343434243]
Then I executed the program using the following command:
./test < junk.txt
which generated the output:
25
I'm currently following this video on how to work with assembly and gdb, using this C program, but I'm running into a problem. Here's what I do to compile and run gdb:
chiggins#host:~/assem$ gcc -ggdb -o SimpleDemo SimpleDemo.c
chiggins#host:~/assem$ gdb ./SimpleDemo
GNU gdb (Ubuntu/Linaro 7.4-2012.04-0ubuntu2) 7.4-2012.04
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
For bug reporting instructions, please see:
<http://bugs.launchpad.net/gdb-linaro/>...
Reading symbols from /home/chiggins/assem/SimpleDemo...done.
(gdb) list
4 int add(int x, int y)
5 {
6 int z =10;
7
8 z = x + y;
9 return z;
10 }
11
12 main(int argc, char **argv)
13 {
(gdb)
14 int a = atoi(argv[1]);
15 int b = atoi(argv[2]);
16 int c;
17 char buffer[100];
18
19 gets(buffer);
20 puts(buffer);
21
22 c = add(a,b);
23
(gdb)
24 printf("Sum of %d+%d = %d\n",a, b, c);
25
26 exit(0);
27
28 }
(gdb) run 10 20
Starting program: /home/chiggins/assem/SimpleDemo 10 20
demo
Now from where I have "demo" typed at the end, that's where the program is supposed to be accepting user input. But when I press return after typing enter, nothing happens. I can't ctrl+c out of the program, can't do anything. I end up having to kill the process from another session just so I can get control back. Any ideas why gdb is doing this, or what I might be doing wrong?
Thanks!
I'm not sure why that doesn't work for you; it works as expected here...
Still, I find it easier to run programs performing interactive I/O in a separate terminal, and perhaps it will help you.
In one terminal,
$ gdbserver --multi localhost:4242
listening on port 4242
and in another,
$ gdb ./SimpleDemo
(gdb) target extended-remote localhost:4242
Remote debugging using localhost:4242
(gdb) run 10 20
Back to the terminal running gdbserver,
Remote debugging from host 127.0.0.1
Process ./SimpleDemo created; pid=PID
demo
demo
Sum of 10+20 = 30
Child exited with status 0
Are you trying to have user input during the program? If you simply want to set command line arguments at the beginning you can just say set args ... where you can give the arguments as you would during the course of the program.
Have you tried this?
gdb --args ./SimpleDemo 10 20
Use Ctrl+Enter instead of the Enter key.
For reference, I'm copying this example (nearly) letter for letter from page 18 in The C Programming Language, Second Edition.
#include <stdio.h>
/*count characters in input, 2nd version*/
main(){
double n;
for (n = 0; getchar() != EOF; ++n)
;
printf("%.0f\n", n); /*this never prints*/
}
I wasn't sure if it was my version of gcc (I'm a noob):
% gcc --version
gcc (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5
Copyright (C) 2010 Free Software Foundation, Inc.
Because
for (n = 0; getchar() != EOF; ++n)
printf("%.0f",n); /*returns 0123456...n*/
I tried printing "foo" instead of value n, just to see. It still isn't printing.
What am I missing here? I don't like moving ahead while ignoring little problems like these.
=====================================
EDIT
So the end result should be:
% gcc ./counter.c -o ./counter
% ./counter
foo
3
Right now, this is the output from the first snippet:
% ./counter
foo
0123
And the second one:
% ./counter
foo
^C
%
If you are on an OSX or linux box, you need to type Ctrl+D on its own line to generate an EOF character. On Windows, Ctrl+Z on its own line. Don't type Ctrl+Z on a unix box because that will just send your proces to the background.
You are typing Ctrl+C which is break, and will send a SIGTERM to your program.
On my mac, I get:
$ ./foo
hello
6D
Or if you don't want to signal the EOF condition, use echo and a pipe:
$ echo "hello" | ./foo
6
Note that the EOF has to be on its own line. a ^D is printed, and then 6 overwrites the ^, so it looks like the output is 6D.
Of course, in the two above examples, the characters being counted are h e l l o \n. If you don't want a newline, do this:
$ echo -n "hello" | ./foo
5
You shouldn't have that semi-colon after the for. That means the only thing in your loop is an empty statement.
Actually, David is correct. The empty statement is the only thing in the loop, but that's fine. It will count the number of characters. Then, outside the loop, it will print the total.
This demo shows that it works as intended (6-character input results in printing 6). However, I would use braces, or keep the indentation as in the original for clarity.