I've got a file with paths . But I can't read them correctly in C .
an example of a line in the file :
C:\Trust\The\process.txt
and I want to have this :
C:\\Trust\\The\\process.txt
But how can I replace antislash by double antislash ?
I've got this function :
/* Replace a string */
char* replace(char* text, char* replace, char* element) {
int i, j, k;
int searchSize = strlen(text);
int replaceSize = strlen(replace);
int size = strlen(element);
char* ret;
if (!searchSize) {
ret = malloc(size + 1);
for (i = 0; i <= size; i++) {
ret[i] = element[i];
}
return ret;
}
int retAllocSize = (strlen(element) + 1) * 2;
ret = malloc(retAllocSize);
int bufferSize = 0;
char* foundBuffer = malloc(searchSize);
for (i = 0, j = 0; i <= size; i++) {
if (retAllocSize <= j + replaceSize) {
retAllocSize *= 2;
ret = (char*) realloc(ret, retAllocSize);
}
else if (element[i] == text[bufferSize]) {
foundBuffer[bufferSize] = element[i];
bufferSize++;
if (bufferSize == searchSize) {
bufferSize = 0;
for (k = 0; k < replaceSize; k++) {
ret[j++] = replace[k];
}
}
}
else {
for (k = 0; k < bufferSize; k++) {
ret[j++] = foundBuffer[k];
}
bufferSize = 0;
ret[j++] = element[i];
}
}
free(foundBuffer);
return ret;
}
I thought I could use like this , but it doesn't work :
char *token ;
char s[]="C:\Trust\The\process.txt";
token=replace("\0x5c","\\",s);
Pulling comments together, you need to understand that the backslash in a string in C source code is an escape charater. It means "the next character has a special meaning".
In order to put a single backslash character in a C string string, you must tell the compiler that "this backslash you must put in the string" and to do that, you put two backslashes in the string in your source code so the string in the compiled code will have a single backslash. In summary:
char s[]= "C:\\my\\dir"";
in your source code, will have a string in the compiled code:
C:\my\dir
If you're reading from an input file input.txt and each filename ends with a newline, this should work:
#define MAX_LINE_LEN 1024
int main(int argc, char *argv[])
{
/* File read variables */
FILE *fp;
char buf[MAX_LINE_LEN];
char *token;
/* Open input file */
fp=fopen(argv[1], "r");
if(fp == NULL)
{
fprintf(stderr, "Unable to open input file. Exiting...");
return 1;
}
/* Get each line and print result */
while ((fgets(buf, sizeof(buf), fp)) != NULL) {
token=replace("\\", "\\\\", buf);
printf("%s", token);
}
fclose(fp);
return 0;
}
Input: input.txt:
C:\Trust\The\process.txt
Output:
C:\\Trust\\The\\process.txt
When you do this:
char s[]="C:\Trust\The\process.txt";
your backslash is gone at compile time. The \T becomes a tab, for example. When you call
token=replace("\0x5c","\\",s);
the contents of s has already been 'edited' by the compiler and the backslashes are gone.
Your test case needs to be
char s[]="C:\\\\Trust\\\\The\\\\process.txt";
and when you call the replace function you will have the single backslashes in s.
There is some confusion in your problem statement:
The variable definition char s[]="C:\Trust\The\process.txt"; is incorrect. It should be written:
char s[] = "C:\\Trust\\The\\process.txt";
The compiler interprets the \ character in a string literal as an escape character to encode special and non-printing characters. The \\ represents a single \ character in the string.
The file contents should not need to have its \ characters doubled or escaped in any way. Unless you perform some sort of parsing when you read the file, the characters read will be stored untouched in memory and the sequence C:\Trust\The\process.txt in the file will be read as a string identical to s.
Related
I am trying to write a function that gets multiple lines if ends with \ and just stop if don't have that. I am very new with C so having trouble to do it.
So something like
User input:
Hello, I am blablabla \
I like bablabla \
My favorite color is (stop here)
But in my current function when the user press enter is over and just the first line is saved.
I know that I need to check if in the end have a backslash just keep going and appending, I am just not sure how to do that using getline.
char *getCommand(void){
char* line; //string from user
ssize_t linesize = 0;
//getting command from user if reaches end of file exit or if something went wrong to read file.
if(getline(&line, &linesize, stdin)==-1){
if(feof(stdin)){
exit(0);
}
else{
fprintf(stderr, "Error reading the command: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
}
return line;
}
What your code is basically doing is reading one line. Few things to note:
feof(stdin) is wrong.
getline() dynamically allocates a string, so you need to free it yourself.
That said, you can implement it this way:
// Returns the number of commands read, -1 if it fails
int getCommand(char **commands, int max_commands)
{
int i, num_cmds = 0;
for (i = 0; i < max_commands; i++) {
char *line = NULL; // This must be initialized to NULL
ssize_t linesize = 0;
if(getline(&line, &linesize, stdin) == -1)
return -1;
line[strcspn(line, "\n")] = '\0'; // Replace \n with a null-terminator
commands[i] = line;
num_cmds++;
if (!strchr(line, '\\')) // if the line doesn't contain a \ then exit
return num_cmds;
}
return num_cmds;
}
commands is an array of strings that will hold your commands. max_commands is the maximum number of commands your array may hold (i.e. its size).
You can use it this way:
int main(void)
{
const int max_commands = 120;
char *commands[max_commands];
int num_cmds = getCommand(commands, max_commands);
if (num_cmds == -1) {
fprintf(stderr, "Error reading commands\n");
return 1;
}
int i;
for (i = 0; i < num_cmds; i++) {
printf("command %d: %s\n", i + 1, commands[i]);
free(commands[i]); // clear memory allocated by getline
}
}
Given your input as an example, here is what you will get:
Hello, I am blablabla \
I like bablabla \
My favorite color is
command 1: Hello, I am blablabla \
command 2: I like bablabla \
command 3: My favorite color is
EDIT: If the \ needs to be at the end of the line, then replace if (!strchr(line, '\\')) with
if (line[strlen(line)-1] != '\\').
You can use this code to solve your problem, I opted to use scanf instead of getline, but the final working is the same:
#include <stdio.h>
#include <stdlib.h>
// Set limit to line
#define LINE_BUFFER 1024
// Get length a string
unsigned int length(const char * str) {
int count = 0;
while (str[count] != '\0') count++;
return count;
}
// Concatenate two strings to a target variable (dest)
int concat(const char * src_1, const char * src_2, char * dest, size_t sizeof_dest) {
// Get lengths from sources
unsigned int src_1_length = length(src_1);
unsigned int src_2_length = length(src_2);
// Calculate minimum length for dest
unsigned int dst_length = src_1_length + src_2_length;
if(sizeof_dest < dst_length)
// Has no minimum length for concatenation
return -1;
int index = 0;
for(int i = 0; i < src_1_length; i++) {
index++;
dest[i] = src_1[i];
}
for(int i = 0; i < src_2_length; i++) dest[index + i] = src_2[i];
return 0;
}
// Read multiline
char * getCommand() {
char * command = NULL;
while(1) {
char line[LINE_BUFFER];
scanf("%[^\n]s", line);
fflush(stdin);
// Get line length
unsigned int line_length = length(line);
// Checking last character
// zero - false
// nonzero - true
char has_slash = line[line_length - 1] == '\\' ? 1 : 0;
// Update slash to breakline
if(has_slash) line[line_length - 1] = '\n';
if(command == NULL) {
command = (char *) malloc(line_length * sizeof(char));
// Copy line to command
for(int i = 0; i < line_length; i++) command[i] = line[i];
} else {
// Concatenate command with current line for command update
unsigned int command_length = length(command);
unsigned int tmp_command_length = line_length + command_length;
char tmp_command[tmp_command_length];
if(concat(command, line, tmp_command, sizeof(tmp_command)) != 0) {
printf("Error in concatenating '%s' with '%s'\n", command, line);
}
// Free memory from old command
free(command);
// Allocating memory for new updated command
command = (char *) malloc(tmp_command_length * sizeof(char));
// Copy command plus current line to new command
for(int i = 0; i < tmp_command_length; i++) command[i] = tmp_command[i];
}
if(!has_slash) break;
}
return command;
}
Click here to access the code repository on Github if you want to improve or fix something. Your collaboration is very welcome.
Quick example of implementation:
Let's assume this is the main file (main.c)
// IMPORTANT: Paste the code above here
// ...
int main() {
char * command = getCommand();
// Print result
printf("\n---- BEGIN ---\n");
printf("\n%s\n", command);
printf("\n---- END ---\n");
// Always clear data allocated in heap memory
free(command);
return 1;
}
Now let's compile the file via terminal, you can use the gcc or clang compilers. In this example I will use clang.
$ clang main.c -o getcommand
(if you are using gcc, just change the clang to gcc)
Run the compiled file:
$ ./getcommand
Right after type your test text
Hello, I am blablabla \
I like blablabla \
My favorite color is
The output should be as follows:
---- BEGIN ---
Hello, I am blablabla
I like blablabla
My favorite color is
---- END ---
I am new to C and am getting very frustrated with learning this language. Currently I'm trying to write a program that reads in a program textfile, reads and prints all the string literals, and tokens each on separate line. I have most of it except for one snag. within the text file there is a line such as: (..text..). I need to be able to search, read and print all the text is inside the parentheses on it's own line. Here is an idea I have so far:
#define KEY 32
#define BUFFER_SIZE 500
FILE *fp, *fp2;
int main()
{
char ch, buffer[BUFFER_SIZE], operators[] = "+-*%=", separators[] = "(){}[]<>,";
char *pus;
char source[200 + 1];
int i, j = 0, k = 0;
char *words = NULL, *word = NULL, c;
fp = fopen("main.txt", "r");
fp2 = fopen ("mynewfile.txt","w") ;
while ((ch = fgetc(fp)) != EOF)
{
// pus[k++] = ch;
if( ch == '(')
{
for ( k = 0;, k < 20, K++){
buffer[k] = ch;
buffer[k] = '\0';
}
printf("%s\n", buffer)
}
....
The textfile is this:
#include <stdio.h>
int main(int argc, char **argv)
{
for (int i = 0; i < argc; ++i)
{
printf("argv[%d]: %s\n", i, argv[i]);
}
}
So far I've been able to read char by char and place it into a buffer. But this idea just isn't working, and I'm stumped. I've tried dabbling with strcopy(), ands strtok, but they all take char arrays. Any ideas would be appreciated thank you.
Most likely the best way would be to use fgets() with a file to read in each line as a string (char array) and then delimit that string. See the short example below:
char buffer[BUFFER_SIZE];
int current_line = 0;
//Continually read in lines until nothing is left...
while(fgets(buffer, BUFFER_SIZE - 1, fp) != NULL)
{
//Line from file is now in buffer. We can delimit it.
char copy[BUFFER_SIZE];
//Copy as strtok will overwrite a string.
strcpy(copy, buffer);
printf("Line: %d - %s", current_line, buffer); //Print the line.
char * found = strtok(copy, separators); //Will delmit based on the separators.
while(found != NULL)
{
printf("%s", found);
found = strtok(NULL, separators);
}
current_line++;
}
strtok will return a char pointer to where the first occurrence of a delimiter is. It will replace the delimiter with the null terminator, thereby making "new" string. We can pass NULL to strtok to tell it to continue where it left off. Using this, we can parse line by line from a file based on multiple delimiters. You could save these individual string or evaluate them further.
I am a beginner in coding and having difficulty trying to take input from both command line as well as console(STDIN). my program is supposed to search and replace a group of characters from a string. For example, concatenate cat gat : the output must be congatenate!
This is my code so far!
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/*Function to replace a string with another string*/
char *rep_str(const char *s, const char *old, const char *new1)
{
char *ret;
int i, count = 0;
int newlen = strlen(new1);
int oldlen = strlen(old);
for (i = 0; s[i] != '\0'; i++)
{
if (strstr(&s[i], old) == &s[i])
{
count++;
i += oldlen - 1;
}
}
ret = (char *)malloc(i + count * (newlen - oldlen));
if (ret == NULL)
exit(EXIT_FAILURE);
i = 0;
while (*s)
{
if (strstr(s, old) == s) //compare the substring with the newstring
{
strcpy(&ret[i], new1);
i += newlen; //adding newlength to the new string
s += oldlen;//adding the same old length the old string
}
else
ret[i++] = *s++;
}
ret[i] = '\0';
return ret;
}
int main(int argc, char*agrv[])
{
char mystr[100], c[10], d[10];
scanf("%s", mystr);
scanf(" %s",c);
scanf(" %s",d);
char *newstr = NULL;
newstr = rep_str(mystr, c,d);
printf("%s\n", newstr);
free(newstr);
return 0;
}
as for now, it shows correct output for either console input or commandline input, bur not both!
kindly suggest the changes to be made!
You can have a check on the variable argc of function int main().
// Path of executable file is passed by default so value of 'argc' will be at least 1
if(argc > 1)
{
// do stuff to work on input from command line
}else{
// do stuff to work on input from STDIN
}
Instead of trying to parse input file through argc and argv, simply pass all the input file through stdin. This means that you will always use scanf to read input data.
At command line you will need to call using pipes, something like this:
$ cat file.txt | yourprogram
I would like to write a program that could read a file, let's say myfile.bin, convert the buffer to binary 'string' ("101110111011..."), store that in a char* variable. Later, I would like to be able to convert that binary 'string' into a binary buffer again and create another file, let's say myanotherfile.bin, with the very same content of the first one.
Please note that I am not trying to read text from files.
I saw many people talking about how to do the first part but, until now, I couldn't find anyone talking about the second one (how to create a binary file from a binary string that was created from a previous file).
UPDATE
This is the code I am using to read a file and generate a 'binary string':
#import <stdio.h>
#import <limits.h>
#import <stdlib.h>
int main() {
char buffer[32];
FILE *file = fopen("myfile.bin","rb");
if (file == NULL) { fclose (file); }
size_t count;
while ((count = fread(buffer, sizeof buffer[0], sizeof buffer, file)) > 0) {
for (size_t j = 0; j < count; j++ ) {
for (int i = CHAR_BIT-1; i >= 0; i--) {
fputc(buffer[j] & (1u << i) ? '1' : '0', stdout);
}
}
}
fclose(file);
return 0;
}
The above code outputs a binary string such as: "1110011101101....".
This would be the first part. The second part would be to take that string and create a file. Is that possible?
Thanks.
Maybe you need something like this:
First of all read your file and save all in a string.
Then you can call this function:
char * string_to_binarystring(char* s,int size)
{
char output[9];
char * return_str = malloc(size*8+1);
return_str[0] = '\0';
while (*s)
{
itoa(*s, output, 2);
strcat(return_str,output);
++s;
}
return return_str;
}
for example in this way:
char string[] = "Hello World";
puts(string_to_binarystring(string,strlen(string)));
At the end print your string into a file.
Hint:
For write into a binary file you need:
char mystring[] = "Hello World";
FILE *ptr_myfile;
ptr_myfile=fopen("test.bin","wb");
if (!ptr_myfile)
{
printf("Unable to open file!");
return 1;
}
fwrite(mystring, strlen(mystring), 1, ptr_myfile);
fclose(ptr_myfile);
N.B. you can find both strlen and strcat into string.h
EDIT:
For rewriting the file as binary you need to convert your binary string into the original string (that you read from the file).
You can use this function:
char * binarystring_to_string(char* s,int size){
char * return_str = malloc(size/8+1);
int i;
char * end;
for(i = 0; i < size/8; i++){
return_str[i] = bits_to_char(s);
printf("\n%c",bits_to_char(s));
s+=8;
}
return_str[i] = '\0';
return return_str;
}
That for works need to use this:
char bits_to_char(char * num){
unsigned char result = 0;
int i;
for ( i = 0; i < 8; ++i )
result |= (num[i] == '1') << (7 - i);
return result;
}
it is quite obvious: do it in opposite direction, like in decimal but with power of 2:
0b10101010 convert to unsigned int like this:
2^8*1 + 2^7*0 + 2^6*1 + ... + 2^1*1 + 2^0*0.
I have a text file which contains words separated by space. I want to take each word from the file and store it. So i have opened the file but am unsure how to assign the word to a char.
FILE *fp;
fp = fopen("file.txt", "r");
//then i want
char one = the first word in the file
char two = the second word in the file
You cannot assign a word to a char. You can assign a single character to a char - hence the name. You can assign a word to an array of characters - such as s[128].
For instance:
char word[128];
fscanf(fp, "%s", word);
Note, in production code you cannot just use statically sized buffer, this will lead to buffer overflow exploitable code.
you can't hold a word in a char variable.It has to be a string or a char pointer that can be enlarged.
try this;
char p[10]; //assuming that a word can have most 10 characters.
FILE *fp;
fp = fopen("file.txt","r");
fscanf(fp,"%s",p);
If you want a bit more flexible - for example: by choosing the characters that identify a word - you could have a look at this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// adjust size for your needs
#define MAX_WORD_LEN 1000
static char *parseable_characters_str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxy0123456789-";
static char parseable_characters_tbl[256] = {0}; // lookup index table, stores yes/no -> allowed/not allowed
/*
* builds the lookup table
*/
void build_lookup_index(char *table, const char *str)
{
int i;
// init table to zero
memset(table,0,256);
// set value to 1 at ASCII-code offset of the array if the character is allowed to be
// part of the word
for (i=0; str[i]; i++)
table[(unsigned char)str[i]] = 1;
}
/*
* returns unparsed bytes (kind of offset for next reading operation)
*/
int parse_buffer(char *buf, int size, const char *lookup_table)
{
int i,l,s;
char word[MAX_WORD_LEN+1];
i = 0;
l = 0;
s = 0;
while (i<size) {
// character not in lookup table -> delimiter
if (!lookup_table[buf[i]] || !buf[i]) {
if (l >= MAX_WORD_LEN) {
fprintf(stderr,"word exceeds bounds\n");
}
else if (l > 0) { // if word has at least 1 character...
// append string-terminator
word[l] = '\0';
printf("word found (%d): '%s'\n",l,word);
}
// reset word length
l = 0;
// save last word offset
s = i+1;
}
else {
// prevent buffer overflows
if (l < MAX_WORD_LEN)
word[l] = buf[i];
l++;
}
if (!buf[i])
break;
i++;
}
if (s > 0 && size-s > 0) {
// move rest of the buffer to the start for next iteration step
memmove(buf,buf+s,size-s);
return size-s;
}
return 0;
}
int main(int argc, char *argv[])
{
FILE *fh;
char buf[1000]; // read buffer
// "rb" because of Windows - we want all characters to be read
fh = fopen("out.txt","rb");
// initialize word index
build_lookup_index(parseable_characters_tbl,parseable_characters_str);
if (fh) {
int r,off = 0;
while (!feof(fh)) {
r = fread(buf+off,1,sizeof(buf)-off,fh);
off = parse_buffer(buf,r,parseable_characters_tbl);
}
fclose(fh);
}
return 0;
}