Concatenate path and variable in C - c

This is my code. I need create 10 files with this format:
0.txt
1.txt
...
But I can't do it, the result is different. Can anyone help?
#include <stdlib.h>
#include <string.h>
char* direccion(char *dirD,int number){
char buffer[100];
char *n;
char *q;
char* formato=".txt";
sprintf(buffer, "%i", number);
n= strcat(dirD,buffer);
q= strcat(n,formato);
return q;
}
int main(){
int u;
int number= 0;
int t= 0;
char* q = "e:/c9/";
for(t=0; t< 10 ; t++){
char* dir = direccion(q,number);
if(fopen(dir,"w")){
fopen(dir,"w");
u=1;
}
else{
u=0;
printf("Error\n");
}
number++;
}
return 0;
}
Thanks !

Problem No 1. is:
char *q = "e:/c9/";
for(t = 0; t < 10; t++)
{
char *dir = direccion(q, number);
}
The variable q is a string literal. However, in the function direccion(), you pass it as the first argument to strcat(), which tries to modify it — BOOM, a segfault. Solution:
char buf[1000];
strcpy(buf, "e:/c9/");
char *dir = direccion(buf, number);
Problem #2 is as #Charlie Martin pointed out is that you return a statically automatically allocated local string, which is invalid after the direccion() function returns. Maybe
return strdup(buffer);
in this case; don't forget to free it after use.
Edit: seems you don't even ask about this. You can create a file using the open() system call (function):
#include <fcntl.h>
#include <stdio.h>
int fd = open("file.txt", O_RDWR | O_CREAT, 0644);
close(fd);
Of course substitute the actual file mode you want for 0644 (but don't make the file executable unless it contains a program to be executed).
Edit 2: I didn't even catch this one... So, in the for loop, you want to reset the base filename over and over:
for (yadda yadda)
{
strcpy(buf, "e:/c9/");
char *dir = direccion(buf, i);
}
etc.

You're allocating the buffer in automatic inside your function, which means it's allocated on the stack. When you return, that memory is no longer valid. You want to allocate the buffer in the caller and pass a pointer to it, or allocate it as static.

Windows has a series of path handling functions that you can use to do things like add an extension to a path.
For example:
PathAddExtension(buffer,".txt");
For more information see http://msdn.microsoft.com/en-us/library/windows/desktop/bb773559(v=vs.85).aspx
Also, it's a good idea to work with buffers of _MAX_PATH size when dealing with paths.

Related

Int to char array as a function returning an array of char the simple way

I have been looking on internet for this and so far i just found a lot of questions for specific answer and not a general one.
i am kind of rusty on C. And i want to make a function that will return an array of char.
this is what i got and is not working. basically a way to convert a byte array to an array of chars to do atoi later..
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
char *get_char(int my_byte[], int packetsize)
{
char *array_char=(char *) malloc(sizeof(char)*10); //trying this but didnt work
// char array_char[10]; //i had it like this before(was told to do it)
for(int i=0;i<10;i++)
{
array_char[i]=my_byte[i]+0;
}
return array_char;
}
int main()
{
int byte_array[]={1,2,3,4,5,6,7,8,9,0};
char *temp;
char data;
temp=get_char(byte_array,10);
data=*temp;
printf("String point %s ",data);
}
Two fixes:
As you want to convert to char, then
array_char[i]=my_byte[i]+0; should be array_char[i]=my_byte[i]+'0'; Note '0' is character (that will be converted to int) instead of numeric 0 (which doesn't do anything).
Also you must free temp pointer in main as that memory is dynamically allocated in get_char() function.
Edit: just notice another issue in your get_char()
char *array_char=(char *) malloc(sizeof(char)*10);
should be
char *array_char= malloc(sizeof(char)*(packetsize+1));
After the for loop, ensure the buffer is NUL-terminated:
array_char[packetsize] = '\0';
Notice that your packetsize is never used - you should get some compiler warning about it. It's bad to hard code 10 in your malloc - it's actually the whole idea of parsing the packetsize as a parameter - so use it properly.
You need to watch out for these things:
You need to add a null-terminating character at the end of *array_char, otherwise using this pointer allocated from the heap will cause undefined behaviour.
You can simply allocate *array_char like this:
char *array_char = malloc(packetsize+1);
As sizeof(char) is 1, and +1 for trailing nullbyte.
You also don't need to cast return of malloc().
Instead of passing 10 as packetsize to get_char(), you should pass this size as sizeof(arr) / sizeof(arr[0], which is the calculated size of the array. This can be a size_t variable declared somewhere or even a macro.
malloc() needs to be checked, as it can return NULL if unsuccessful.
You need to free() temp at some point in the program.
array_char[i]=my_byte[i]+0; needs to be array_char[i]=my_byte[i]+'0'; instead, as '0' is the ascii code for a zero character.
char data needs to be char *data, as temp is a pointer.
If you compile with -Wall -Wextra, you will see that this line:
data=*temp;
Is dangerous, and will trigger warnings of making pointers from integers without a cast. It will most likely lead to a segmentation fault. If temp and data are both pointers, then you can simply use:
data=temp;
Which sets data to the address of temp. Sometimes this is written as data = &(*temp);, but this is harder to read. Although their is no need for data, and using temp alone should be fine.
Your code can then look like this:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define ARRAYSIZE(arr) (sizeof(arr) / sizeof(arr[0]))
char *get_char(int my_byte[], size_t packetsize) {
char *array_char = malloc(packetsize+1);
const char ascii = '0';
size_t i;
if (!array_char) {
printf("Cannot allocate %zu bytes\n", packetsize+1);
exit(EXIT_FAILURE);
}
for(i = 0; i < packetsize; i++) {
array_char[i] = my_byte[i] + ascii;
}
array_char[i] = '\0'; /* or array_char[packetsize] = '\0' */
return array_char;
}
int main(void) {
int byte_array[]={1,2,3,4,5,6,7,8,9,0};
char *temp, *data;
temp = get_char(byte_array, ARRAYSIZE(byte_array));
data = temp;
printf("String point %s\n", data);
printf("String converted into number = %d\n", atoi(data));
free(temp);
temp = NULL;
return 0;
}
You can also look into strtol, which is better than using atoi() in terms of error checking.
It is Not Wise Idea to Return a Array From A Function. So how to return a string then? As most of libc functions use we can use some thing like that (i.e) passing a buffer along with our input and expect function to use output buffer to give us result.
Some issue to take care while coding
write your logic first.
try to use available functions from libc.
while dealing with byte data/binary data be take precaution of buffer overflow.
don't allocate in a function and de-allocate in another function.
Below is Example of your code with modification.
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include <stdint.h>
int get_char(uint8_t my_byte[], int packetsize, char *buffer, int max_buffer)
{
int byte_itr, buf_itr;
char temp_buf[16]={0x00};
for(byte_itr=0, buf_itr=0; byte_itr<packetsize && max_buffer > buf_itr; byte_itr++)
{
memset(temp_buf, 0x00, sizeof(temp_buf));
char temp_ch = my_byte[byte_itr];
snprintf(temp_buf, sizeof(temp_buf), "%d", temp_ch);
if( buf_itr+strlen(temp_buf) >=max_buffer){
break;
}else{
buf_itr += strlen(temp_buf);
strcat(buffer, temp_buf);
if(byte_itr+1 < packetsize){
strcat(buffer, ",");
buf_itr += 1;
}
}
}
return buf_itr;
}
int main()
{
uint8_t byte_array[]={1,2,3,4,5,6,7,8,9,0};
char char_array[32]={0x00};
int len = get_char(byte_array, 10, char_array, sizeof(char_array));
printf("String point %s : len %d\n", char_array, len);
}
NOTE:
when length return and size of output buffer same then buffer full condition happened.

C: System calls and pointers to reverse a file

Solved. Thanks lutogniew.....just over complicating it...
So I am having some trouble with a homework assignment. The assignment is to take in a file (using only system calls), reverse it and write an output file with that reversed data on it (ASCII only). A catch is that the reverse section has to be done with pointers. I did the following below, which does work. However, it does not use pointers to reverse.
My question I guess, is how can I access something like data[] using pointers? Or, how can I read from the file into it. Everything I tried (mostly char**) only reads in null.
Any help would be much appreciated.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
int main(void)
{
int i = 0;
int fileOut = open("output.txt", O_WRONLY | O_APPEND);
int fileIn = open("input.txt", O_RDONLY);
int start = lseek(fileIn, 0 , SEEK_CUR);
int end = lseek(fileIn, 0 , SEEK_END);
int restart = lseek(fileIn, 0-end , SEEK_CUR);
char data[end];
char reverseData[end];
read(fileIn, data, end);
for(i = 0; i< end; i++){
reverseData[i] = data[end-(i+1)];
}
write(fileOut, reverseData, end);
return 0;
}
After Accept Answer.
Something for OP to consider as another approach:
For fun, a not-so-serious recursive approach to reverse the file.
void reverse(int fileIn, int fileOut) {
char data;
if (read(fileIn, &data, 1) == 1) {
reverse(fileIn, fileOut);
write(fileOut, &data, 1);
}
}
int main(void) {
int fileOut = open("output.txt", O_WRONLY | O_APPEND);
int fileIn = open("input.txt", O_RDONLY);
reverse(fileIn, fileOut);
close(fileIn);
close(fileOut);
return 0;
}
You must understand that what is presented to you as an array in C, in reality is just a pointer, pointing to the beginning of the memory belonging to that array. This snippet should make everything quite clear:
int test[] = { 1, 2, 3 };
int* ptr = test + 2; // ptr now points to the third element
EDIT
As for loading data into an array: again, remember that array itself is just a pool of memory (a buffer) - it begins where the pointer mentioned above points to, and has the size equal to numberOfElements * sizeOfSingleElement. Now look at the signature of the read function:
size_t read(int fildes, void* buf, size_t nbytes);
It reads nbytes into buffer pointed to by buf. Rings a bell?

C OS X Read Directory Contents into String Array

I am trying to get the contents of a directory. Ideally, I would like to store them in a string array. Is there a way to do this in c other than opening the directory, iterating through its contents, and populating an array as it goes?
I am working on a system running OS X 10.9
You can obtain an allocated directory listing with the POSIX scandir function, which takes a path and optional filtering and sorting callbacks, and returns an array of dirent structures. OS X also provides an equivalent function which takes blocks rather than callbacks for sorting and filtering.
int scandir(const char *dirname, struct dirent ***namelist,
int (*select)(const struct dirent *),
int (*compar)(const struct dirent **, const struct dirent **));
Just retrieving an unsorted list of entries is very straightforward:
int num_entries;
struct dirent **entries = NULL;
num_entries = scandir("/", &entries, NULL, NULL);
for(int i = 0; i < num_entries; i++)
puts(entries[i]->d_name);
//entries is ours to free
for(int i = 0; i < num_entries; i++)
free(entries[i]);
free(entries);
POSIX also provides a pre-made sorting function to use with scandir for alphabetical ordering. To use it, just pass alphasort as the last argument.
Be careful of scandir returning an error (-1). The above code is structured in such a way that an explicit check isn't necessary, but that may not be possible in more elaborate uses.
You might want to run using system libc call and fopen.
Here is the sample code, take care of all the array lengths, there is NO validation done here.
#include
#include
#include
int
main(int argc, char* argv[])
{
char cmd[254] = "ls ";
char arr[1024];
char line[254];
FILE *fp;
if(argc < 2) return -1;
if(argv[1]) strcat(cmd, argv[1]);
strcat(cmd, " > /tmp/out");
system(cmd);
fp = fopen("/tmp/out", "r");
if(!fp){
perror("");
return fprintf(stderr, "could not open /tmp/out!\n");
}
while(fgets(line, 254, fp) != NULL) {
strcat(arr, line);
}
printf("%s\n", arr);
return 0;
}

I wrote a substr function in c, but can not get the returned value in main function

I wrote a substr function in c, I can get the returned value inside the substr function, but can not get the returned value in main function. Below is all the code:
#include <stdio.h>
#include <string.h>
char* substr(char *source, int start, int length)
{
char result[10];
char *r = result;
strncpy(result, source+start, length);
printf("substr: %s\n", r);
return r;
}
int main()
{
printf("main: %s\n", substr("HELLO", 1, 2));
}
and the output is:
substr: EL
main:
I'm not familiar with c, anybody get the idea to fix this, thanks in advance.
result only exists during the call to your substr.
Your main is referencing bad memory.
you could fix it by:
making result static in substr.
dynamically allocating result (remember to free)
making result global
As cthulhu ( "Ph'nglui mglw'nafh Cthulhu R'lyeh wgah'nagl fhtagn" ) points out: even if you applied one of my fixes: your string isn't nul terminated.
Also since you have a fixed size result buffer, you could cause problems by asking for a substring longer than 10 - either check your arguments, or don't use a fixed size buffer.
I haven't tested this, so there may well be an "off by one" problem or two lurking in the corners...
/*
* Caller must free the results if they are non null
*/
char* substr(char *source, int start, int length)
{
/* If the input is NULL, return NULL */
if (source == NULL) return NULL;
int len = strlen(source);
/* If the requested start is off the end of the string, return NULL */
if (start > len) return NULL;
/* If the requested length is 0 or less, return NULL */
if (length <= 0) return 0;
char *r = (char*)malloc(length + 1); /* allow space for null terminator */
if (r != NULL) {
int i = 0;
while(source[start] != '\0' && i < length) {
r[i++] = source[start++];
}
r[i] = '\0';
printf("substr: %s\n", r);
}
return r;
}
If you're going to be expecting to return a value to the caller then you should pass the place where the string will be stored to the function. Standard library functions like strcpy do this. Here is a very simple example. It assumes dest is already declared and is big enough to store it.
char * substr(char * dest, char * src, int start, int length)
{
// Move substring into passed destination pointer
strncpy(dest, src + start, length);
// Append null to the end to terminate string
dest[length] = 0;
// Return string pointer that can be used in printf and other places
return dest;
}
int main(int argc, char const *argv[])
{
char * test = "This is a test.";
char * dest = malloc(10);
printf("%s", substr(dest, test, 5, 2));
free(dest);
return 0;
}
Output:
is
Edit: To all the people returning values that are malloc'd inside the function, how do you expect people to free the memory if they just use it in a print statement? They receive no pointer to free and the memory will just be left hanging there.
The below code allocate memory on the heap. Just free your memory when you are done. strlcpy always NUL-terminate its strings as others have pointed out.
#include <string.h>
char *
substr(char *s, int start, int len)
{
char *ss;
if(strlen(s) < start + len)
return NULL;
if((ss = malloc(len + 1)) == NULL)
return NULL;
strlcpy(ss, s + start, len);
return ss;
}
int
main(void)
{
char *s = substr("Hello World!", 6, 5);
printf("%s\n", s);
free(s);
return 0;
}
Should print World.
To use strlcpy in Debian Linux use:
gcc -lcext -o prog prog.c
If your operating system doesn't provide strlcpy just include it yourself in your source. It is licensed under the BSD license, that means free to use, sell, etc, as long you include the license itself.
The implementation of strlcpy can be found on OpenBSD's CVS Web.
Dynamic and Static Variables in C
Variable declarations can be outside all functions or inside a function
Declarations outside all functions are global and in fixed memory locations
The static declaration declares a variable outside a function to be a “file global” (cannot be referenced by code in other source files)
Declarations within a block statement {} (function body or block statement nested within a function body):
Are dynamically allocated, unless declared static
Are allocated memory when program execution enters the block
Memory is released when execution exits the block
If a function calls itself (directly or indirectly), it gets a new set of dynamic variables (called a stack frame)
This is handled no differently from any other call to the function
You have problem, the variable result[] is a variable that has been allocated in side the function — whose lifetime extends across the entire run of the function(allocated at the stack!) because of that you need to make the result Dynamic variable
Fix code:
#include <stdio.h>
#include <string.h>
char* substr(char *source, int start, int length)
{
char* result;
char *r;
result=(char*)malloc(sizeof(char)*10);
r = result;
strncpy(result, source+start, length);
printf("substr: %s\n", r);
return r;
}
int main()
{
char* r=substr("HELLO", 1, 2);
printf("main: %s\n",r );
free(r)//Don't forget to free it!
}
OR you can make result[] global variable like this:
#include <stdio.h>
#include <string.h>
char result[10];//<======Global
char* substr(char *source, int start, int length)
{
char *r=result;
r = result;
strncpy(result, source+start, length);
printf("substr: %s\n", r);
return r;
}
int main()
{
printf("main: %s\n",substr("HELLO", 1, 2));
}

read file of 10 lines of integer, put them in a array, and output the array

In this program, i want to let user to input 2 arguments, the number
of integer,and the file name.
the file has 10 lines of integer value.
read the file, and put it to inArray[];
and then output it as the end;
notes: For the complete program, i want to make a program that
will scan a file consists of random integer,and then sort
them in ascend order, and print out the first 10 percent
of the sorted integer.
Error: For now, i want to test if it can read the file and put values
into the inArray properly, but its keep getting errors.
warning: initialization makes integer from pointer without a cast
findTotal.c:43:6: warning: passing argument 1 of ‘fopen’
makes pointer from integer without a cast
/usr/include/stdio.h:271:14: note: expected ‘const
char * __restrict__’ but argument is of type ‘char’
Please help me with this, thank you
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[]){
int numOfInt;
char fileName="";
sscanf(argv[1],"%d",&numOfInt);
sscanf(argv[2],"%c",&fileName);
int i, rc;
/* the origninal list , initialise as 0 index*/
int inArray[numOfInt];
/* the number of output int */
int outNumInt = numOfInt * 0.1;
/* the output array of int */
int outArray[outNumInt];
FILE *inFile;
inFile = fopen(fileName,"r");
/* check if the file is empty */
if(inFile==NULL){
printf("can not open the file");
}
for (i = 0; (rc = getc(inFile)) != EOF && i < numOfInt; inArray[i++] = rc)
{
}//for
fclose(inFile);
for(i = 0; i < numOfInt;i++){
printf("%x\n",inArray[i]);
}
}//main
I think you could be using scanf better here. You use it to read in two pieces of information that should have been passed as arguments to the program, and then refreain from using it for what it would actually be good for, which is reading the file in question. Here is my take at this:
#include <stdlib.h>
#include <stdio.h>
int cmp(const void *a, const void *b) { return *(int*)b - *(int*)a; }
int main(int argc, char *argv[])
{
char * ifile = argv[1];
int n = atoi(argv[2]), m = n/10, i;
int nums[n];
FILE * f = fopen(ifile, "r");
for(i = 0; i < n; i++) fscanf(f, "%d", &nums[i]);
qsort(nums, n, sizeof(int), cmp);
for(i = 0; i < m; i++) printf("%d\n",nums[i]);
return 0;
}
If this file is prog.c and the corresponding executable is prog, and your file with numbers is called nums.txt, and contains 100 integers, you would call this as
prog nums.txt 100
The advantage of taking in parameters this way is that it makes repeating the command later easier (all the information needed to repeat it will be in the command history of the shell), and that it is the standard way of passing parameters to a program. It also frees up standard input for other uses.
You have indeed a problem with the filename's management. char is for characters; if you want to handle a file name, you have to use a string. In C, we can use an array of char, terminated by a nul-character. Here, because argv[2] holds directly the name, you can simply use a pointer.
char *fileName = argv[2];
And then:
fopen(fileName, "r");
Since you don't modify the argv pointer, you can also send directly argv[2] as argument.
One of the problems I see in your code is:
char fileName="";
sscanf(argv[2],"%c",&fileName)
A string literal is a constant string, which means you shouldn't attempt to modify it, you should either use a static (or dynamic) char array for that string and use the %s format specifier, or just point fileName to argv[2]
char *fileName;
fileName = argv[2];

Resources