So I am just trying to learn C and have decided to program a simple calendar where you can add events etc. It is working almost perfectly however, when it tries to read from the file containing the information, the first line contains some strange characters : �<�}�U1.
Code is as follows:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void createCalendar(char filename[]) {
FILE *cptr;
cptr = fopen(filename, "w");
char dates[177/sizeof(char)] = "";
for(int i = 1; i < 32; i++) {
char strtowrite[7/sizeof(char)] = "";
sprintf(strtowrite, "%d - \n", i);
strcat(dates, strtowrite);
}
fprintf(cptr, "%s", dates);
fclose(cptr);
}
void addToDay(char filename[], int day, char event[]) {
FILE *cptr;
cptr = fopen(filename, "r");
char *line = NULL;
size_t len = 0;
ssize_t read;
char dates[177/sizeof(char) + strlen(event)/sizeof(char)];
int i = 1;
while ((read = getline(&line, &len, cptr)) != -1) {
if (i==day) {
char strtowrite[7/sizeof(char) + strlen(event)/sizeof(char)];
sprintf(strtowrite, "%d - %s\n", i, event);
strcat(dates, strtowrite);
}
else {
strcat(dates, line);
}
i += 1;
}
printf("%s", dates);
fclose(cptr);
cptr = fopen(filename, "w");
fprintf(cptr, "%s", dates);
fclose(cptr);
}
int main() {
createCalendar("january");
addToDay("january", 12, "event");
}
and the first line of output is: í¬_<89>lU1 - (in the file)
Try this
char dates[177/sizeof(char) + strlen(event)/sizeof(char)] = {0};
in your addToDay function when declaring the dates variable. I think that you do not set the memory there, so there might be some junk in that memory location.
Get specific content from a file and store it in a variable. So far I get that I can convert the file content into a string. But I'm not sure how can I 'extract' the content from the string I converted and would like some help.
The original file looks something like this:
XXXXXX
XXXXX
Addr = 12:23:34:45:45
XXX
XXX
I need to extract and store the Addr as a string. Want to look for the prefix Addr = and just copy it into a buffer. But I don't know how can I do it...
So far my code looks like below:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
//So far I'm looking for it using the MAC addr format
const char *get_mac_addr(char *str, char *dest) {
if (str == NULL)
return 0;
char *start = NULL;
int token_count = 0;
char *ptr = str;
if (*ptr && *(ptr + 1)) // skip two chars in the beginning of the string
ptr += 2;
else
return 0;
while (*ptr != '\0' && *ptr != '\n' && *ptr != '\r') {
if (token_count == 5)
break;
/* if ':' found and previous two characters are hexidecimal digits then
the substring could be part of MAC
*/
if (*ptr == ':' && isxdigit(*(ptr - 1)) && isxdigit(*(ptr - 2))) {
token_count++;
if (start == NULL)
start = ptr - 2;
int i = 0;
while (*ptr != '\0' && i++ < 3)
ptr++;
} else {
start = NULL;
token_count = 0;
ptr++;
}
}
strcpy(dest, start);
return dest;
}
const char *file2str(){
/* declare a file pointer */
FILE *infile;
char *buffer;
long numbytes;
char dest[18];
/* open an existing file for reading */
infile = fopen("~/Desktop/file.config", "r");
/* quit if the file does not exist */
//if (infile == NULL)
// return 1;
/* Get the number of bytes */
fseek(infile, 0L, SEEK_END);
numbytes = ftell(infile);
/* reset the file position indicator to
the beginning of the file */
fseek(infile, 0L, SEEK_SET);
/* grab sufficient memory for the
buffer to hold the text */
buffer = (char *)calloc(numbytes, sizeof(char));
/* memory error */
//if(buffer == NULL)
// return 1;
/* copy all the text into the buffer */
fread(buffer, sizeof(char), numbytes, infile);
fclose(infile);
/* confirm we have read the file by
outputing it to the console */
printf("The file called test.dat contains this text\n\n%s", buffer);
//memset(dest, '/0', sizeof(dest));
get_mac_addr(buffer, dest);
/* free the memory we used for the buffer */
//free(buffer);
printf("Dest is \n\n%s", dest);
return dest;
}
int main() {
printf(file2str);
return 0;
}
I really appreciate your help. Please bare with me as I'm not very good at c programming. I would like to convert the main function into one function so I can directly call it and return a string. I converted the main function as following, but I'm not sure why when I print it, there is nothing show up:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
FILE * xfopen(const char *path, const char *mode);
const char *MACadd()
{
char buf[256];
char *addr = NULL;
FILE *in = xfopen("~Desktop/file.config", "r");
while( fgets(buf, sizeof buf, in) ){
addr = strstr(buf, "Addr = ");
if( addr && addr < buf + sizeof buf - ADDRLEN){
addr += strlen("Addr = ");
addr[ADDRLEN] = '\0';
break;
}
}
//printf("addr = %s\n", addr);
return addr;
}
FILE *xfopen(const char *path, const char *mode)
{
FILE *fp = fopen(path, mode);
if( fp == NULL ){
perror(path);
exit(EXIT_FAILURE);
}
return fp;
}
int main(){
printf("%s", MACadd());
return 0;
}
You could read the file line by line with the fgets function and use the sscanf function to extract the relevant portion like that:
#include <stdio.h>
#include <ctype.h>
#include <stdbool.h>
#define ISXDGT(c) isxdigit((unsigned char)(c))
static bool is_macaddr (const char *s)
{
return ISXDGT(s[0]) && ISXDGT(s[1]) && s[2] == ':'
&& ISXDGT(s[3]) && ISXDGT(s[4]) && s[5] == ':'
&& ISXDGT(s[6]) && ISXDGT(s[7]) && s[8] == ':'
&& ISXDGT(s[9]) && ISXDGT(s[10]) && s[11] == ':'
&& ISXDGT(s[12]) && ISXDGT(s[13]) && s[14] == ':'
&& ISXDGT(s[15]) && ISXDGT(s[16]);
}
bool get_macaddr_from_file (const char *filename, char *macaddr)
{
char line[4096];
bool done = false;
FILE *fp = fopen(filename, "r");
if (fp == NULL) {
fprintf(stderr, "Cannot open the file '%s'\n", filename);
return false;
}
while (fgets(line, sizeof line, fp) != NULL) {
/* Modify the prefix (" Addr = " here) at your convenience */
if (sscanf(line, " Addr = %17s", macaddr) == 1 && is_macaddr(macaddr)) {
done = true;
break;
}
}
fclose(fp);
return done;
}
int main (void)
{
char macaddr[18];
if (get_macaddr_from_file("file.conf", macaddr)) {
printf("MAC: %s\n", macaddr);
}
}
char *extract(const char *str, char *buff)
{
char *addr = strstr(str, "Addr");
if(addr)
{
addr += sizeof("Addr") - 1;
while(!isdigit((unsigned char)*addr))
{
if(*addr == '\n' || !*addr)
{
addr = NULL;
break;
}
addr++;
}
if(addr)
{
while(*addr && *addr != '\n' && (isdigit(*addr) || *addr == ':'))
{
*buff++ = *addr++;
}
*buff = 0;
}
}
return addr ? buff : NULL;
}
void main(int argc, char** argv)
{
char *str = "XXXXXX\nXXXXX\n\nAddr = 12:23:234:145:45 \nXXX\nXXX\n";
char mac[30];
if(extract(str,mac)) printf("Hurray!!! `%s`\n", mac);
else printf("MIsareble failure\n");
}
https://godbolt.org/z/6TjK8b
This gets a little tricky if you don't want to restrict yourself to a fixed maximum line length, but it's probably sufficient to do something like:
#define ADDRLEN 14
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
FILE * xfopen(const char *path, const char *mode);
int
main(int argc, char **argv)
{
char buf[256];
char *addr = NULL;
FILE *in = xfopen(argc > 1 ? argv[1] : "-", "r");
while( fgets(buf, sizeof buf, in) ){
addr = strstr(buf, "Addr = ");
if( addr && addr < buf + sizeof buf - ADDRLEN){
addr += strlen("Addr = ");
addr[ADDRLEN] = '\0';
break;
}
}
printf("addr = %s\n", addr);
}
FILE *
xfopen(const char *path, const char *mode)
{
FILE *fp = path[0] != '-' || path[1] != '\0' ? fopen(path, mode) :
*mode == 'r' ? stdin : stdout;
if( fp == NULL ){
perror(path);
exit(EXIT_FAILURE);
}
return fp;
}
To break this into a function, you need to be a little bit careful. In your attempt, you've passed back references to local variables which cease to exist after the function returns. Perhaps you want something like:
#define ADDRLEN 14
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
FILE * xfopen(const char *path, const char *mode);
const char *
MACadd(const char *path, char *buf, size_t s)
{
char *addr = NULL;
FILE *in = xfopen(path, "r");
while( fgets(buf, s, in) ){
addr = strstr(buf, "Addr = ");
if( addr && addr < buf + s - ADDRLEN){
addr += strlen("Addr = ");
addr[ADDRLEN] = '\0';
break;
}
}
return addr;
}
FILE *xfopen(const char *path, const char *mode)
{
FILE *fp = fopen(path, mode);
if( fp == NULL ){
perror(path);
exit(EXIT_FAILURE);
}
return fp;
}
int
main(void)
{
char buf[256];
printf("%s", MACadd("input", buf, sizeof buf));
return 0;
}
I think that is easier than you are doing, once you moved the file contnent in a string, use strstr() - here ther is the description http://www.cplusplus.com/reference/cstring/strstr/ - to find "addr = " and then get the string from there to the character "\n"
follow this example
#include<string.h>
#include<stdio.h>
#define endchrptr(ptr1, ptr2, ptr3) (ptr1 < ptr2 ? (ptr1<ptr3?ptr1:ptr3) : (ptr2<ptr3?ptr2:ptr3))
bool get_mac_addr(const char* source, char *dest) {
if(source!=NULL&&dest!=NULL) {
char* addr_pointer=strstr(source, "Addr = ")+7;//find where the address start
char* end_addr_pointer=endchrptr(strchr(addr_pointer, '\n'), strchr(addr_pointer, '\r'), strchr(addr_pointer, '\0'));//find where the address ends
if(end_addr!=NULL) {
for(int i=0; i<end_addr_pointer-addr_pointer; ++i) {//copy the address
dest[i]=addr_pointer[i];
}
dest[end_addr_pointer-addr_pointer],
}
else return false;
}
else return false;
}
int main()
{
char *str = "XXXXXX\nXXXXX\n\nAddr = 12:23:234:145:45 \nXXX\nXXX\n";
char mac[30];
get_mac_addr(str, mac);
printf("%s", mac);
}
I just tried in DevC++ and it works.
Let me know if it works.
There are multiple problems in the code:
fopen("~/Desktop/file.config", "r"); will fail because the ~ in the filename is not expanded to the home directory by fopen, it is a feature of the command shell. Use the full path instead, or take the filename as an argument.
you do not check for fopen() failure: passing a null stream pointer to fseek has undefined behavior and will probably crash the program.
printf(file2str); is a major mistake: you try to use the bytes from the function as a format string, you will get garbage output and possibly a crash because of undefined behavior. Use printf("%s\n", file2str()); instead.
there is no need to read the whole file in memory at once for this problem, just reading one line at a time is much simpler. Furthermore, you do not allocate enough memory for the null terminator, so you get undefined behavior with using buffer as a C string.
get_mac_addr is way too complicated: you could use strstr to locate the string "Addr = " and extract the following word.
Here is a simpler version:
#include <ctype.h>
#include <stdio.h>
#include <string.h>
const char *get_mac_address(const char *str, char *dest) {
if (!strncmp(buf, "Addr = ", 7)) {
const char *p = buf + 7;
for (i = 0; i < 17; i++) {
if (i % 3 == 2) {
if (p[i] != ':')
break;
} else {
if (!isxdigit((unsigned char)p[i]))
break;
}
}
if (i == 17 && !isalnum((unsigned char)p[i]) {
memcpy(dest, p, 17);
dest[17] = '\0';
return dest;
}
}
return NULL;
}
int main() {
char buf[256];
char address[20];
FILE *fp = fopen("/home/ImTrying/Desktop/file.config", "r");
if (fp != NULL) {
while (fgets(fp, buf, sizeof buf)) {
if (get_mac_address(buf, address)) {
printf("Dest is %s\n", address);
break;
}
}
fclose(fp);
}
return 0;
}
i am trying to read from a text file and store it into an array character by character, ive tested it out by trying to print or check the ii count but it doesn't seem to be storing, any help would be muchly appreciated
char *readFile(char* filename)
{
FILE* f;
int ii = 0;
char* file = (char*)malloc(1000*sizeof(char));
char ch = '\0';
f = fopen(filename,"r");
if(f == NULL)
{
printf("Error opening file '%s'.\n", filename);
}
else
{
while ((ch = fgetc(f)) != EOF)
{
printf("%c",ch);
file[ii] = (char) ch;
ii++;
}
}
/* file[ii] = '\0'; setting last character as null*/
printf("\n");
fclose(f);
free(file);
return file;
}
I have commented out the line containing the code to free the character array before returning, which was basically making the pointer invalid. I have also changed the type of the variable "ch" to int as fgetc() returns integer.
#include <stdio.h>
#include <stdlib.h>
char *readFile(char* filename)
{
FILE* f;
int ii = 0;
char* file = (char*)malloc(1000*sizeof(char));
int ch; //changed to int from char.
f = fopen(filename,"r");
if(f == NULL)
{
printf("Error opening file '%s'.\n", filename);
}
else
{
while ((ch = fgetc(f)) != EOF)
{
// printf("%c",ch);
file[ii] = (char) ch;
ii++;
}
}
/* file[ii] = '\0'; setting last character as null*/
printf("\n");
fclose(f);
//free(file); //commented this line out
return file;
}
int main()
{
char *filename = "sample.txt";
char *file_arr = readFile(filename);
printf("%s \n",file_arr);
return 0;
}
Im new to c and am trying to understand pointers.
here I am opening a file and reading the lines given. Im trying to append these lines into an array and return it from the function. I dont seem to be appending or accessing the array correctly. output[count] = status; gives an error with mismatched char and char *.
Im essentially trying to get an array with a list of words given by a file where each element in the array is a word.
char *fileRead(char *command, char output[255]) {
int count = 0;
char input[255];
char *status;
FILE *file = fopen(command, "r");
if (file == NULL) {
printf("Cannot open file\n");
} else {
do {
status = fgets(input, sizeof(input), file);
if (status != NULL) {
printf("%s", status);
strtok(status, "\n");
// add values into output array
output[count] = status;
++count;
}
} while (status);
}
fclose(file);
return output;
}
I access fileRead via:
...
char commandArray[255];
char output[255];
int y = 0;
char *filename = "scriptin.txt";
strcpy(commandArray, fileRead(filename, output));
// read from array and pass into flag function
while (commandArray[y] != NULL) {
n = flagsfunction(flags, commandArray[y], sizeof(buf), flags.position, &desc, &parentrd, right, left, lconn);
y++;
...
Example of Read from file Line by line then storing nonblank lines into an array (array of pointer to char (as char*))
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//for it does not exist because strdup is not a standard function.
char *strdup(const char *str){
char *ret = malloc(strlen(str)+1);
if(ret)
strcpy(ret, str);
return ret;
}
//Read rows up to 255 rows
int fileRead(const char *filename, char *output[255]) {
FILE *file = fopen(filename, "r");
if (file == NULL) {
perror("Cannot open file:");
return 0;
}
int count = 0;
char input[255];
while(count < 255 && fgets(input, sizeof(input), file)) {
char *line = strtok(input, "\n");
if(line)//When it is not a blank line
output[count++] = strdup(line);//Store replica
}
fclose(file);
return count;
}
int main(void){
char *output[255];//(`char *` x 255)
int number_of_read_line = fileRead("data.txt", output);
for(int i = 0; i < number_of_read_line; ++i){
printf("%s\n", output[i]);
free(output[i]);//Discard after being used
}
return 0;
}
I have an elf file that called example. I wrote following code which it's read the content of the example file in the binary mode and then I wanted to save their content in another file called example.binary. But when I run the following program it shows me a segmentation fault. What's wrong with this program? I can't find out my mistake.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// typedef macro
typedef char* __string;
//Function prototypes
void readFileToMachine(__string arg_path);
int main(int argc, char *argv[]) {
__string pathBinaryFile;
if(argc != 2){
printf("Usage : ./program file.\n");
exit(1);
}
pathBinaryFile = argv[1];
readFileToMachine(pathBinaryFile);
return EXIT_SUCCESS;
}
void readFileToMachine(__string arg_path){
int ch;
__string pathInputFile = arg_path;
__string pathOutputFile = strcat(pathInputFile, ".binary");
FILE *inputFile = fopen(pathInputFile, "rb");
FILE *outputFile = fopen(pathOutputFile, "wb");
ch = getc(inputFile);
while (ch != EOF){
fprintf(outputFile, "%x" , ch);
ch = getc(inputFile);
}
fclose(inputFile);
fclose(outputFile);
}
You have no room to concatenate extention to path so you have to create space for that.
One solution could be:
char ext[] = ".binary";
pathOutputFile = strdup(arg_path);
if (pathOutputFile != NULL)
{
pathOutputFile = realloc(pathOutputFile, strlen(arg_path) + sizeof(ext));
if (pathOutputFile != NULL)
{
pathOutputFile = strcat(pathInputFile, ext);
// YOUR STUFF
}
free(pathOutputFile);
}
Side note: typedef a pointer is not a good idea...
change your typedef to typedef char* __charptr
void rw_binaryfile(__charptr arg_path){
FILE *inputFile;
FILE *outputFile;
__charptr extension = ".binary";
__charptr pathOutputFile = strdup(arg_path);
if (pathOutputFile != NULL){
pathOutputFile = realloc(pathOutputFile, strlen(arg_path) + sizeof(extension));
if (pathOutputFile != NULL){
pathOutputFile = strcat(pathOutputFile, ".binary");
inputFile = fopen(arg_path, "rb");
outputFile = fopen(pathOutputFile, "wb");
write_file(inputFile, outputFile);
}
}
}
void write_file(FILE *read, FILE *write){
int ch;
ch = getc(read);
while (ch != EOF){
fprintf(write, "%x" , ch);
ch = getc(read);
}
}