I read the other articles for finding the file extension from a filename in C and I've tried them but the problem is that they don't work correctly.
This is my code :
void optionOne()
{
char filenameSrc[101],filenameDest[101];
strcpy(filenameSrc,"");
do
{
printf("Enter source filename (*.c) : ");
scanf("%s",filenameSrc);
}while (check_file_ext(filenameSrc) != 0);
fflush(stdout);
printf("Enter destination filename : ");
scanf("%s",&filenameDest);
char line[80];
FILE* fp = fopen("data.inp","r");
while(fgets(line,sizeof(line),fp))
{
// do something
}
fclose(fp);
}
and the function check_file_ext :
const char *get_file_ext(const char *filename)
{
const char *dot = strrchr(filename, '.');
if(!dot || dot == filename) return "";
return dot + 1;
}
int check_file_ext(const char* filename)
{
return strcmp(get_file_ext(filename),"c") == 0;
}
The problem is in the check method for the file extension?
Could you tell me where is the problem in the code?
Don't return "", return a pointer to '\0' byte instead:
// gcc -std=c99
#include <stdio.h>
#include <string.h>
static const char*
get_file_ext(const char *filename) {
const char *ext = strrchr(filename, '.');
return (ext && ext != filename) ? ext : (filename + strlen(filename));
}
int main() {
char *files[] = {"a.c", ".a", "a", NULL };
for (char** f = files; *f != NULL; ++f)
printf("ext: '%s'\n", get_file_ext(*f));
}
Note: it ncludes . in the extension for consistency.
Output
ext: '.c'
ext: ''
ext: ''
Reverse condition: do{ ... }while(strcmp(get_file_ext(filename), ".c") != 0);
Related
it's a cesar encrypt in process
the problem is when i open a file with the method "openFile"
/* it's been 2 years since I've touched the c language, I'm getting back to it */
i have this code other file :
//method to encrypt a char
char encrypt(char c, int jump) {
int overflow = 0;
char res = c;
char tabChars[26] = {'a','b','c','d','e','f','g','h',
'i','j','k','l','m','n','o','p','q',
'r','s','t','u','v','w','x','y','z'};
for(int i=0;i<sizeof (tabChars);i++) {
if(c == tabChars[i]) {
if(i+jump > 25) {
overflow = i+jump - 26;
res = tabChars[overflow];
} else if(i+jump <= 25) {
res = tabChars[i+jump];
}
}
}
return res;
};
void writeInFile(FILE* file) {
//todo
};
// error here
void openFile(char* file) {
FILE* f = fopen(file, "r");
printf("\nopen file : %s\n", file);
char c;
while((c = getc(f)) != EOF) {
putchar(c);
}
fclose(f);
};
and main code :
int jump = 5;
char c = 't';
printf("\nletter change with : --%c--\n",encrypt(c,jump));
char* file = "taget/to/message.txt";
openFile(file); // error here
but i have a error :
Invalid parameter passed to C runtime function.
Invalid parameter passed to C runtime function.
why doesn't work ? thanks all
with if(f) // works, thx all for your comments
void openFile(char* file) {
FILE* f = fopen(file, "r");
if(f) {
printf("\nopen file : %s\n", file);
char c;
while((c = getc(f)) != EOF) {
putchar(c);
}
fclose(f);
} else {
printf("\nopen error...\n");
}
};
out of function :
Hello i have a problem when i try to read conf file (line by line)
this is my code :
bool EndWith(const char* haystack, const char* needle)
{
bool rv = 0;
if (haystack && needle)
{
size_t needle_size = strlen(needle);
const char* act = haystack;
while (NULL != (act = strstr(act, needle)))
{
if (*(act + needle_size) == '\0')
{
rv = 1;
break;
}
act += needle_size;
}
}
return rv;
}
FILE *file2 = fopen ("config.conf", "r");
const size_t line_size = 300;
char* line = malloc(line_size);
while (fgets(line, line_size, file2) != NULL) {
puts(line);
if(EndWith(line, "toto")) {
puts("yes");
}
}
and my conf file :
vm.user_reserve_kbytes = 131072 toto
vm.vfs_cache_pressure = 100 toto
vm.zone_reclaim_mode = 0 toto
My code return 2 "Yes" but if my conf file, if i add a line feed in first line i read my 3 lines and my code return 3 "Yes"
Why ?
i want to return 3 "Yes" without need to add a line feed in line0 of my conf file
bug retrurn :
vm.user_reserve_kbytes = 131072 toto
yes
vm.vfs_cache_pressure = 100 toto
yes
vm.zone_reclaim_mode = 0 toto
correct return (with add a line feed)
yes
vm.user_reserve_kbytes = 131072 toto
yes
vm.vfs_cache_pressure = 100 toto
yes
vm.zone_reclaim_mode = 0 toto
i tested solution Filip Kočica (thanks for your help) but i have same problem :
the code:
bool EndWith(const char* haystack, const char* needle)
{
if (haystack == NULL || needle == NULL)
{
return false;
}
const char* p;
if ((p = strstr(haystack, needle)) != NULL)
{
if (!strcmp(p, haystack + strlen(haystack) - strlen(needle)))
{
return true;
}
}
else
{
return false;
}
return false;
}
int main(int argc, char **argv)
{
FILE *file2 = fopen ("config.conf", "r");
const size_t line_size = 300;
char* line = malloc(line_size);
while (fgets(line, line_size, file2) != NULL) {
puts(line);
if (EndWith(line, "za"))
{
puts("it does.");
}
}
return 0;
}
my file config.conf :
vm.user_reserve_kbytes = 131072 za
vm.vfs_cache_pressure = 1001 za
vm.zone_reclaim_mode = 01 za
1]
It return's 2 becouse last row doesn't end with new line character \n.
Everytime you call getline it gives you one line from file (If there is another line).
There is no need for checking if this line really end's with NL character.
Just count how many times getline didn't return EOF.
Get puts out of condition
while (fgets(line, line_size, file2) != NULL)
{
puts(line);
puts("yes");
if(EndWith(line, /*special strings*/ ))
{
}
}
2]
bool EndWith(const char* haystack, const char* needle)
{
if (haystack == NULL || needle == NULL)
{
return false;
}
const char* p;
if ((p = strstr(haystack, needle)) != NULL)
{
if (!strcmp(p, haystack + strlen(haystack) - strlen(needle) - 1))
{
return true;
}
}
else
{
return false;
}
return false;
}
int main(int argc, char **argv)
{
FILE *file2 = fopen ("config.conf", "r");
const size_t line_size = 300;
char* line = malloc(line_size);
while (fgets(line, line_size, file2) != NULL) {
if (EndWith(line, "za"))
{
puts("it does.");
}
puts(line);
}
return 0;
}
config file:
vm.user_reserve_kbytes = 131072 za
vm.vfs_cache_pressure = 1001 za
vm.zone_reclaim_mode = 01 za
OUTPUT:
it does.
vm.user_reserve_kbytes = 131072 za
it does.
vm.vfs_cache_pressure = 1001 za
it does.
vm.zone_reclaim_mode = 01 za
I'm trying to read from a file using C and after shrinking the size using realloc I get corrupted data. I don't really see what the problem could be.
Here's the function that returns the string :
char *read_string(FILE *fichier) {
char car = 0;
size_t size = 1;
char *symbole = realloc(NULL, sizeof(char) * size);
char *s;
size_t len = 0;
if (!symbole)
return symbole;
else
s = symbole;
do {
car = getc(fichier);
} while (car != '"' && car != EOF);
if (car == EOF)
return EOFP;
else {
car = getc(fichier);
while (car != '"' ) {
s[len] = car;
car = getc(fichier);
len++;
if (len == size) {
symbole = realloc(s, sizeof(char) * (size += 1));
if (!symbole)
return symbole;
else
s = symbole;
}
}
s[len] = '\0' ;
symbole = realloc(s, sizeof(char) * len);
if (!symbole) {
printf("WTF");
return symbole;
} else
s = symbole;
return s;
}
}
My main function is:
int main(int argc, char *argv[]) {
FILE *fichier = NULL;
fichier = fopen("C:/Users/Nabila K/Documents/test.json", "r");
if ((fichier != NULL)) {
while (feof(fichier) == 0) {
char *test = read_string(fichier);
if (test == NULL) {
printf("test == NULL\n");
exit(1);
} else
if (test == EOFP) {
} else {
printf("%s\n", test);
free(test);
}
}
fclose(fichier);
} else {
exit(EXIT_FAILURE);
}
return 0;
}
UPDATE
My json file looks something like this :
{
"KARIM BENNI" : {
"2017-08-07 09:50:50" : {
"Anomalie" : {
"description" : "Test",
"theme" : "Engins mobiles"
},
"date" : "2017-08-07",
"date_now" : "2017-08-07 09:50:50",
"entite" : "USINE LAMINAGE A FROID",
"etat" : "Cree",
"nb_personne" : 2,
"temps" : 5,
"visiteur" : "KARIM BENNI",
"visite" : "AHMED RABII",
"zone" : "COUPE"
}
}
}
There are multiple issues in your code:
char car = 0; is incorrect: you must define car as int to correctly distinguish all values returned by getc(), especially EOF.
while (feof(fichier) == 0) is always wrong. Learn why there: Why is “while ( !feof (file) )” always wrong?
EOFP is not defined, you should probably use NULL instead for more clarity.
the final realloc() to shrink the allocated block is one byte too short. You must keep len+1 bytes for len characters plus the null terminator.
Here is a simplified and corrected version:
#include <stdio.h>
#include <stdlib.h>
char EOFP[1]; /* special value used to signal end of file */
char *read_string(FILE *file) {
int c;
size_t size, len;
char *symbol;
char *s;
while ((c = getc(file)) != '"') {
if (c == EOF)
return EOFP;
}
size = 16;
len = 0;
symbol = malloc(size);
if (symbol == NULL) {
/* allocation failure */
return NULL;
}
while ((c = getc(file)) != '"') {
if (c == EOF) {
/* premature end of file in the middle of a string */
free(symbol);
return EOFP;
}
if (len + 2 < size) {
size += size;
s = realloc(symbol, size);
if (s == NULL) {
/* allocation failure */
free(symbol);
return NULL;
}
symbol = s;
}
symbol[len++] = c;
}
symbol[len] = '\0';
s = realloc(symbol, len + 1);
return s ? s : symbol;
}
int main(int argc, char *argv[]) {
FILE *file = fopen("C:/Users/Nabila K/Documents/test.json", "r");
if (file != NULL)) {
char *test;
while ((test = read_string(file)) != EOFP) {
if (test == NULL) {
printf("test == NULL\n");
exit(1);
} else {
printf("%s\n", test);
free(test);
}
}
fclose(file);
} else {
exit(EXIT_FAILURE);
}
return 0;
}
Notes:
Parsing the full JSON syntax for strings would be required if the strings can contain escaped characters such as \" or \n, \\ etc.
char IP[32] = "";
char PORT[4] = "0000";
int read_conf()
{
int i;
char line[25] = "";
FILE *fp;
char *str_ptr;
fp = fopen("client.conf","r");
for(i=1;(fgets(line,sizeof(line),fp));i++)
{
if(1==i)
{
str_ptr = strstr(line,"IP:");
if(str_ptr)
{
strcpy(IP,(str_ptr+3));
}
else
{
printf("Error in fetching IP \n");
exit(0);
}
}
else if(2==i)
{
str_ptr = strstr(line,"Port:");
if(str_ptr)
{
strcpy(PORT,(str_ptr+5));
}
else
{
printf("Error in fetching PORT \n");
exit(0);
}
}
}
return 1;
}
char *construct_url(int n,char * const argv[])
{
char * final_url;
int i,k=2;
int j = 0;
final_url = malloc(sizeof(char *)*300);
strcpy(final_url,"http://");
strcat(final_url,IP);
strcat(final_url,":");
strcat(final_url,PORT);
strcat(final_url,"/");
//printf("%s",final_url);
for(i=1;i<n,k>0;i++,k--)
{
strcat(final_url,argv[i]);
if(i==1)
{
strcat(final_url,"/");
}
else
{
strcat(final_url,"?");
}
}
return final_url;
}
In my above code it is adding a newline after IP and PORT value which is not correct URL construction. how do I avoid new line before concatenation.
client.conf consist
IP:10.12.130.216
Port:5200
Expected Result:
http://10.12.130.216:5200/
Getting Result:
http://10.12.130.216
:5200
/
read_conf can be written in simple as follows using fscanf.
char PORT[6] = "00000";//0-65535
int read_conf(void){
FILE *fp = fopen("client.conf","r");
if(1 != fscanf(fp, "IP:%31s\n", IP)){
printf("Error in fetching IP \n");
exit(0);
}
if(1 != fscanf(fp, "Port:%5s", PORT)){
printf("Error in fetching PORT \n");
exit(0);
}
fclose(fp);
return 1;
}
If you are sure that it is a new line, use:
strcat(final_url,IP);
strtok(final_url, "\n");
strcat(final_url,":");
strcat(final_url,PORT);
strtok(final_url, "\n");
strcat(final_url,"/");
or use strtock function separately for IP and PORT strings.
Hi I am having trouble with this function. For some reason weird values are appended to the string at random times.
/* ex: path = /usr/src/data returns: /usr/src */``
char* get_pathname(char* path) {
char* pathname;
char* temp;
int filenamelength;
int pathlength;
temp = get_filename(path); //name of file within original path
filenamelength = strlen(temp);
printf("strlen(temp) %d\n", strlen(temp));
printf("strlen(path) %d\n", strlen(path));
pathlength = strlen(path);
pathname = malloc((pathlength-filenamelength-1));
strncpy(pathname, path, pathlength-filenamelength-1);
return pathname;
}
/* ex: path /usr/src/data returns: data */
char* get_filename(char* path) {
char* get_filename(char* path){
char* filename;
char* temp = strrchr(path, '/')+1; //name of file within original path
filename = malloc(sizeof(char) * (strlen(path) + 1));
strcpy(filename, temp);
return filename;
}
strncpy doesn't 0-terminate when the copied string is larger than or exactly fits the passed size.
pathname = malloc((pathlength-filenamelength-1));
strncpy(pathname, path, pathlength-filenamelength-1);
Change to:
pathname = malloc(pathlength-filenamelength);
^^^
strncpy(pathname, path, pathlength-filenamelength-1);
pathname[pathlength-filenamelength-1] = 0;
static void *
xmalloc(size_t n)
{
void *obj = malloc(n);
if (obj == NULL) {
perror("xmalloc");
exit(EXIT_FAILURE);
}
return obj;
}
char *
get_pathname(const char *path)
{
char *slash = strrchr('/', path);
if (slash == NULL) {
char *dot = xmalloc(2);
strcpy(dot, ".");
return dot;
}
char *parent = xmalloc((slash - path) + 1);
memcpy(parent, path, slash - path);
parent[slash - path] = '\0';
return parent;
}
char *
get_filename(const char *path)
{
const char *slash = strrchr('/', path);
const char *filename = (slash == NULL) ? "" : (slash + 1);
char *result = xmalloc(strlen(filename) + 1);
strcpy(result, filename);
return result;
}
I've added the missing error handling and the cases when there is no slash in the given path. In your original code you had a memory leak in get_pathname: you called malloc via get_filename, but didn't free this memory after you used it.
Will this work for you?
char *get_path(char *path)
{
char *fpath = NULL;
char *slash = NULL;
if(path == NULL) goto error;
fpath = strdup(path);
if(fpath == NULL) goto error;
slash = strrchr(fpath, '/');
if(slash != NULL) *slash = '\0';
error:
return fpath;
}
char *get_filename(char *path)
{
char *slash = NULL;
char *fname = NULL;
if(path == NULL) goto error;
slash = strrchr(path, '/');
fname = (slash != NULL) ? strdup(slash + 1) : NULL;
error:
return fname;
}