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.
Related
When I try to print the copyright symbol © with printf or write, it works just fine:
#include <stdio.h>
int main(void)
{
printf("©\n");
}
#include <unistd.h>
int main(void)
{
write(1, "©\n", 3);
}
Output:
©
But when I try to print it with wprintf, I get (C):
#include <stdio.h>
#include <wchar.h>
int main(void)
{
wprintf(L"©\n");
}
Output:
(C)
It's fixed when I add a call to setlocale, though:
#include <stdio.h>
#include <wchar.h>
#include <locale.h>
int main(void)
{
setlocale(LC_ALL, "");
wprintf(L"©\n");
}
Output:
©
Why is the original behavior present and why is it fixed when I call setlocale? Additionally, where does this conversion take place? And how can I make the behavior after setlocale the default?
compilation command:
gcc test.c
locale:
LANG=en_US.UTF-8
LANGUAGE=
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=
echo $LC_CTYPE:
uname -a:
Linux penguin 4.19.79-07511-ge32b3719f26b #1 SMP PREEMPT Mon Nov 18 17:41:41 PST 2019 x86_64 GNU/Linux
file test.c (same on all of the examples):
test.c: C source, UTF-8 Unicode text
gcc --version:
gcc (Debian 6.3.0-18+deb9u1) 6.3.0 20170516
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
/lib/x86_64-linux-gnu/libc-2.24.so (glibc version):
GNU C Library (Debian GLIBC 2.24-11+deb9u4) stable release version 2.24, by Roland McGrath et al.
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 6.3.0 20170516.
Available extensions:
crypt add-on version 2.1 by Michael Glad and others
GNU Libidn by Simon Josefsson
Native POSIX Threads Library by Ulrich Drepper et al
BIND-8.2.3-T5B
libc ABIs: UNIQUE IFUNC
For bug reporting instructions, please see:
<http://www.debian.org/Bugs/>.
cat /etc/debian_version:
9.12
The locale of the calling processes is not automatically inherited by the new process.
When the program first starts up, it is in the C locale. The man page for setlocale(3) says the following:
On startup of the main program, the portable "C" locale is selected
as default. A program may be made portable to all locales by calling:
setlocale(LC_ALL, "");
...
The locale "C" or "POSIX" is a portable locale; its LC_CTYPE part corresponds to the 7-bit ASCII character set.
So any multibyte / non-ASCII character is converted into one or more ASCII characters as the output shows.
The locale can be set as follows:
setlocale(LC_ALL, "");
The LC_ALL flag specifies changing all locale-related variables. An empty string for the locale means to set the locale according to the relevant environment variables. Once this is done, you should see the characters for your shell's locale.
#include <stdio.h>
#include <wchar.h>
#include <locale.h>
int main()
{
char *before = setlocale(LC_ALL, NULL);
setlocale(LC_ALL, "");
char *after = setlocale(LC_ALL, NULL);
wprintf(L"before locale: %s\n", before);
wprintf(L"after locale: %s\n", after);
wprintf(L"©\n");
wprintf(L"\u00A9\n");
return 0;
}
Output:
before locale: C
after locale: en_US.utf8
©
©
I'm trying to remove a file in a folder using C but it's crashing & throwing me some return value
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
FILE *fp1;
char str[100];
gets(str);
strcat(str,"txt");
fp1 = fopen(str,"r");
fclose(fp1);
remove(str);
return 0;
}
This is not working. I'm using windows XP SP2 (32 bit) and also tried system() command in the C program, but No help. Can anyone please help to fix this issue?
It is unclear why you are calling fopen, you are not reading anything from it. If you are attempting to use it as a check for the file's existence, there is no need, the return from remove will tell you whether the removal was successful.
For example, you could do something like the following:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
#define EXT ".txt"
#ifndef PATH_MAX
#define PATH_MAX 4096
#endif
int main (void) {
char buf[PATH_MAX] = "";
size_t len = 0;
printf ("enter filename to delete (without .txt); ");
if (!fgets (buf, sizeof buf, stdin) || *buf == '\n') {
fprintf (stderr, "error: EOF or invalid input.\n");
return 1;
}
len = strlen (buf); /* get length */
if (buf[len - 1] == '\n') /* check trailing '\n' */
buf[--len] = 0; /* overwrite with '\0' */
else {
/* handle error, input exceeded buf size */
return 1;
}
strcat (buf, EXT);
errno = 0;
if (remove (buf) == -1)
perror ("remove failed");
else
printf ("file: '%s' successfully removed.\n", buf);
return 0;
}
Example Use/Output
$ ls -al foobar.txt
-rw-r--r-- 1 david david 0 Sep 17 06:35 foobar.txt
$ ./bin/rmfile
enter filename to delete (without .txt); foobar
file: 'foobar.txt' successfully removed.
$ ./bin/rmfile
enter filename to delete (without .txt); foobar
remove failed: No such file or directory
It works the same on Linux or DOS (you just need to define PATH_MAX on windows).
Example Use/Output on Windows
c:\Users\david\Documents\dev\src-c\tmp>cl /Wall /Ox /Febin\rmfile rmfile.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.30319.01 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.
rmfile.c
Microsoft (R) Incremental Linker Version 10.00.30319.01
Copyright (C) Microsoft Corporation. All rights reserved.
/out:bin\rmfile.exe
rmfile.obj
c:\Users\david\Documents\dev\src-c\tmp>echo "test on Windoze" > foobar.txt
c:\Users\david\Documents\dev\src-c\tmp>dir foobar.txt
Volume in drive C has no label.
Volume Serial Number is 2045-D579
Directory of c:\Users\david\Documents\dev\src-c\tmp
09/17/2017 06:56 AM 20 foobar.txt
1 File(s) 20 bytes
0 Dir(s) 20,235,399,168 bytes free
c:\Users\david\Documents\dev\src-c\tmp>bin\rmfile
enter filename to delete (without .txt); foobar
file: 'foobar.txt' successfully removed.
c:\Users\david\Documents\dev\src-c\tmp>bin\rmfile
enter filename to delete (without .txt); foobar
remove failed: No such file or directory
I guess if you are on windows, you should probably define the following at the top of the file to remove the strcat warning from the compiler:
#if defined (_WIN32) || defined (_WIN64)
#define _CRT_SECURE_NO_WARNINGS
#endif
I made .c file to use in JNI. .java, .h, .c and compiled nicely:D
My environment is Windows 7 64 bits.
However, the problem that I am facing is about another external library.
I received a library that consists of one header file and one lib file.
What I did is below.
I. copy XXX.h and XXX.lib into the same physical directory where original JNI files are.
in my case: C:\Users\JY\worspace\Test\org\owls\src\jni\ and now I have these files in there:
Original files:
IIS.java
IIS.class
org_owls_jni_IIS.h
IIS.c
Newly added:
XXX.h
XXX.lib
II. added the directive #include "XXX.h" to the .c file. So IIS.c now looks like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "org_owls_jni_IIS.h"
#include "XXX.h"
JNIEXPORT jint JNICALL Java_org_owls_jni_IIS_doIIS
(JNIEnv* env, jobject jobj, jstring jtarget, jstring jdest, jstring jimage){
jboolean iscp;
int video_len = 0;
char* a = "aaa";
const char* ctarget = (*env)->GetStringUTFChars(env, jtarget, &iscp);
const char* cdest = (*env)->GetStringUTFChars(env, jdest, &iscp);
const char* cimage = (*env)->GetStringUTFChars(env, jimage, &iscp);
fprintf(stderr, "VIDEO [ %s ] THUMBNAIL [ %s ]\n", ctarget, cdest);
sprintf(tmp, "C : %s\t%s", ctarget, cdest);
fprintf(stderr, "%s\n", tmp);
Call_XXX(a);
(*env)->ReleaseStringUTFChars(env, jtarget, ctarget);
(*env)->ReleaseStringUTFChars(env, jdest, cdest);
(*env)->ReleaseStringUTFChars(env, jimage, cimage);
return (jint)video_len;
}
Call_XXX() is defined in XXX.h and it receives an argument type of char *.
III. compiling with the cl command via VS2012 x64 Native Tools Command Prompt.
Command line is:
cl IIS.c -Feiis.dll -LD -MD
cl IIS.c -Feiis.dll -LD -MD -link XXX.lib
IV. Now the problem comes. Normally, If adding a header file succeeds, there's no problem with calling a function which is declared in that header. But in my case, there's an error. Symptoms are below.
just adding the header file does not result in a compiler error (the compilation succeededs.)
Using the function that is declared in the header file results in a linker error (LNK2019).
error messages are :
IIS.c
Microsoft (R) Incremental Linker Version 11.00.50727.1
Copyright (C) Microsoft Corporation. All rights reserved.
/out:iis.dll
/dll
/implib:iis.lib
IIS.obj
iis.lib 라이브러리 및 iis.exp 개체를 생성하고 있습니다.
IIS.obj : error LNK2019:Call_XXX 외부 기호(참조 위치: Java_org_owls_jni_IIS_doIIS 함수)에서 확인하지 못했습니다.
iis.dll : fatal error LNK1120:
I erased some messages, because those are not in English. But since I left the error codes, I guess that there is no problem with recognizing causes and the situation.
You need to tell the linker that in can look into XXX.lib for any functions it needs to link. It doesn't do that just because the file is in your project directory.
One way to do that is in some source file that is complied, say in IIS.c, after #include "XXX.h"
#pragma comment(lib, "XXX.lib")
See this MS Knowledge Base article.
My environment is Windows XP SP3 + 'Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.762 for 80x86'. The process is as follows:
F:\workshop\vc8proj\console> type t.c
int main(void) {
// Do some thing.
{
int i;
{
i = 3;
goto abc111;
}
abc111:
}
return 0;
}
F:\workshop\vc8proj\console> cl /MD t.c Microsoft (R) 32-bit C/C++
Optimizing Compiler Version 14.00.50727.762 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.
t.c t.c(10) : error C2143: syntax error : missing ';' before '}'
F:\workshop\vc8proj\console>vim t.c
F:\workshop\vc8proj\console>type t.c
int main(void) {
// Do some thing.
{
int i;
{
i = 3;
goto abc111;
}
abc111: 5201314;
}
return 0;
}
F:\workshop\vc8proj\console> cl /MD t.c Microsoft (R) 32-bit C/C++
Optimizing Compiler Version 14.00.50727.762 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.
t.c Microsoft (R) Incremental Linker Version 8.00.50727.762 Copyright
(C) Microsoft Corporation. All rights reserved.
/out:t.exe t.obj
F:\workshop\vc8proj\console>
Under the Linux operating system the same situation, too???
It's a language feature. A label can only be part of a labeled statement, and the statement needs a terminating ;. Just putting a semicolon behind the label suffices.
int main(void) {
// Do some thing.
{
int i;
{
i = 3;
goto abc111;
}
abc111: ;
}
return 0;
}
works too.
Well, it is a language feature. It is compulsory that there should be a statement to which we mentioned the label.
If there isn't any statement after the label then just put a ';' to terminate the statement or you can write a return statement after the label only.
FILE *out=fopen64("text.txt","w+");
unsigned int write;
char *outbuf=new char[write];
//fill outbuf
printf("%i\n",ftello64(out));
fwrite(outbuf,sizeof(char),write,out);
printf("%i\n",write);
printf("%i\n",ftello64(out));
output:
0
25755
25868
what is going on?
write is set to 25755, and I tell fwrite to write that many bytes to a file, which is at the beginning, and then im at a position besides 25755?
If you are on a DOSish system (say, Windows) and the file is not opened in binary mode, line-endings will be converted automatically and each "line" will add one byte.
So, specify "wb" as the mode rather than just "w" as #caf points out. It will have no effect on Unix like platforms and will do the right thing on others.
For example:
#include <stdio.h>
#define LF 0x0a
int main(void) {
char x[] = { LF, LF };
FILE *out = fopen("test", "w");
printf("%d", ftell(out));
fwrite(x, 1, sizeof(x), out);
printf("%d", ftell(out));
fclose(out);
return 0;
}
With VC++:
C:\Temp> cl y.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.21022.08 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.
y.c
Microsoft (R) Incremental Linker Version 9.00.21022.08
Copyright (C) Microsoft Corporation. All rights reserved.
/out:y.exe
C:\Temp> y.exe
04
With Cygwin gcc:
/cygdrive/c/Temp $ gcc y.c -o y.exe
/cygdrive/c/Temp $ ./y.exe
02
It may depend on the mode in which you opened the file. If you open it as a text file, then \n may be written as \r\n in DOS/Windows systems. However, ftello64() probably only gives the binary file pointer, which would count in the extra \r characters written. Try clearing the outbuf[] of any \n data or try opening the out file as binary ("wb" instead of "w").
The variable write is uninitialized and so the size of the array and the amount written will be essentially random.
Interesting. Works fine on Windows VC++, albeit ftello64 replaced with ftell.