I have a simple C code as below :
#pragma warning(disable : 4996)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <process.h>
#include <math.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <windows.h>
#include <tchar.h>
int main()
{
int ndsc;
char *line = ' ';
FILE *fd;
int x;
wchar_t path[256];
wcscpy(path, L"C:/");
//wcscat(path, L"common\\descr.txt", wcslen(L"common\\descr.txt"));
//Previous
wcscat(path, L"common/descr.txt");
if ((fd = _wfopen(path, L"r")) == NULL)
{
printf("Can't open %s for reading.\n", path);
return 1;
}
for (ndsc = 0; fgetws((wchar_t*)line, 80, fd) != NULL; ndsc++)
{
x = wcslen((const wchar_t*)line);
printf("Length of %d line is %d\n", ndsc, x);
}
fclose(fd);
return 0;
}
I am trying to read a file called descr.txt from C:\Common directory. But in for loop it throws unhandled exception as below :
Can anybody explain me why I am getting this error and how to resolve.
By the way this code is being used in an .arx file of AutoCad. I just extracted the part which is throwing error and tried to run it as a standalone project in VS 2015 Update 3. This code is a part of .C file being called by from .NET. Even when executing in the context of .arx ( From AutoCad Clicking on the desired menu ) got the same exception.
Thanks in Advance.
Here: char *line = ' '; You assign a char to a char *.
Later you try to use a wide string buffer. You need wchar_t line[80] to actually allocate space for 80 wchar_t.
The variable line is a pointer, it points to the address 32 (using ASCII encoding).
That address is hardly a valid address to write a string of input.
You need to make it point to some memory big enough to fit the whole string you read (including the terminator). Or have it be an array.
Since the pointer is incorrect you will have undefined behavior, which makes your whole program ill-formed and invalid.
Furthermore, that you need to cast it in the call to fgetsw is another sign of you doing something wrong, and that is using the wrong type (char instead of wchar_t).
Line is a pointer to some illegal address casted from int value of ascii code of ' '.
instead of char *line = ' ';
make it (if you want line to be an array of chars)
char line[80 * sizeof(wchar_t)];
You arre trying to assign a char to a char * by using simple quotes.
If you want to directly assign an int or a char to a char *, use double quotes (" "), or, if it is a single char, you might want to proceed as follows:
char line[0] = ' ';
Make sure that your pointer has been malloc'd and it should do the trick.
A string of digits can later be re-converted to an int using atoi() if you want.
Related
I am trying to read a file line by line, and get each line as a charĀ * to a dynamic string, the code I am using used to work and without changing it (or noticing it), it has ceased to work, accsesing the reed information results in an error. Here is a MRE of my code for getting one line:
#include <stdio.h>
#include <string.h>
#define MAX_STR_SIZE 10000
int main(void)
{
char* filePath; // is set by other working part of program to a real readable file address.
while (fgetc(filePath) != EOF) // an extra chracter is in the data files to account for this cheack.
{
char tempStr[MAX_STR_SIZE] = { 0 };
char* str = NULL;
fgets(tempStr, MAX_STR_SIZE, filePath);
tempStr[strcspn(tempStr, "\n")] = 0;
str = malloc(sizeof(char) * (strlen(tempStr) + 1)); // does not work
strcpy(str, tempStr);
}
}
The error:
Exception thrown at 0x00007ff95448d215 in GifProject.exe: Access violation writing location 0xFFFFFFFFEA1854F0.
It is difficult to diagnose your problem without a complete compilable program that exhibits the problem, but from the code fragment and the debugging information in the image, it seems you do not include <stdlib.h> and the prototype inferred by the compiler for malloc() from the actual argument is int malloc(size_t), leading to undefined behavior when you store the return value into the pointer str: because of the missing prototype, the compiler generates code that converts the return value from int to char *, sign extending from 32-bit to 64-bits, producing a meaningless pointer.
Note that you should also test the return value of fgets to properly handle end of file, and you should test for potential malloc failure before calling strcpy or better: use strdup that allocates and copies a string in a single call.
Here is a modified version:
#include <stdlib.h>
#include <string.h>
#define MAX_STR_SIZE 4096
char *readline(FILE *file) {
char tempStr[MAX_STR_SIZE];
if (!fgets(tempStr, sizeof tempStr, file)) {
/* end of file: return a null pointer */
return NULL;
}
/* strip the trailing newline if any */
tempStr[strcspn(tempStr, "\n")] = '\0';
/* allocate a copy of the string and return it */
return strdup(tempStr);
}
I'm trying to figure out why this doesn't work.
I'd like to take data from a file using the 'getline()' function and convert the string so that the slashes ('/') that are not in quotes are replaced with new line characters. I'd like to avoid copying the string to another if possible.
I tried my program below, with two attempts to process the same data. The first attempt wasn't quite right. I expected to see the following in both cases:
ABC
DEF'/'GH
But
printf("%s",newline);
only returns this:
ABC
DEF'/'
and:
printf("%s",newline2);
returns a segmentation fault.
Because the getline() function returns the string as a char array with memory pre-allocated to it, I feel a ridiculous solution would be:
char lines[5000000];
strcpy(lines,datafromgetline);
char* newline=parsemulti(lines,10); //prints data almost correctly
printf("%s",newline);
But could I somehow do this where I don't have to allocate local stack space or memory? Can I somehow modify the incoming data directly without a segmentation fault?
#define _GNU_SOURCE
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
// replaces all occurrences of / not within single quotes with a new line character
char* parsemulti(char* input,int inputlen){
char* fms=strchr(input,'/');
char output[100000]; //allocate tons of space
if (!fms){
return input;
}else{
int exempt=0,sz=inputlen;
char aline[5000];
char*inputptr=input,*lineptr=aline;
memset(aline,0,5000);
while(--sz >= 0){
if (*inputptr=='\''){exempt=1-exempt;} //toggle exempt when ' is found
if (*inputptr=='/' && exempt==0){
*lineptr='\0';
strcat(output,aline);
lineptr=aline;
strcat(output,"\r\n");
}else{
*lineptr=*inputptr;lineptr++;
}
inputptr++;
}
if (exempt==1){printf("\nWARNING: Unclosed quotes\n");}
*lineptr='\0';
strcat(output,aline);
strcat(output,"\r\n");
}
strcpy(input,output);
return input;
}
int main(){
char lines[5000];
strcpy(lines,"ABC/DEF'/'GH");
char* newline=parsemulti(lines,10); //prints data almost correctly
printf("%s",newline);
char* lines2="ABC/DEF'/'GH";
char* newline2=parsemulti(lines2,10); //returns segmentation fault
printf("%s",newline2);
return 0;
}
Two lines
char lines[5000];
strcpy(lines, "ABC/DEF'/'GH");
will
allocate memory for 5000 objects of type char on stack
copy string literal contents to memory pointed by name "lines", which you can modify
on the other hand
char *lines2 = "ABC/DEF'/'GH";
defines pointer to string literal that is usually located in read only memory.
Read only, as in do not modify me :)
You tagged this C so I assume You are talking about using getline() function - not a part of C standard, but provided by GNU C Library, that manages memory on it's own (so basically it can, and will do memory allocations, unless you preallocate it. It uses only heap memory, so if preallocated size is too small it reallocates it. Thus You can't provide address to stack char array instead).
To actually find and replace escape character from string, I'd say you should not reinvent wheel and use library string functions.
char *line = NULL;
char *needle;
ssize_t line_size;
size_t size = 0;
line_size = getline(&line, &size, stdin);
while (line_size != -1) {
needle = strchr(line, '/');
while (needle) {
if (needle != line && !(*(needle - 1) == '\'' && *(needle + 1) == '\''))
*needle = '\n';
needle = strchr(needle + 1, '/');
}
printf("%s", line);
line_size = getline(&line, &size, stdin);
}
I need to get a clue in how know when to stop storing a string from a file after i hit a space between the words. After i open a file and read it, for example: the first line that is there is:427 671 +. I need to store "427" in an array of int, same with "671" and "+"in a variable.
So far i have figure out how to read the whole line and print it but the problem i have is to read char by char and store it before i hit a space.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <float.h>
#include <Laboratorio.h>
#include <string.h>
int main(int argc, char **argv) {
FILE *datos;
FILE *resultados;
char bin[64]="",hex[16]="";
int oct[21];
ep = fopen ( argv[1], "r" );
if (ep==NULL) {
printf("Archivo vacio.");
return 0;
}else{
while (fgets(bin,64,ep)!=NULL){
printf("%s",bin);
}
fclose(ep);
}
}
The simplest way to do so would be to have a char variable and store each char into it one by one like so:
while ((ch = getc(stream)) != EOF)
{
// do stuff with char
}
after you get the char you can decide what to do with it, compare it to 32 (space) to know when to stop.
if the char is a numeral you can place it in a buffer until you reach a space, then all you need to do is use the function atoi which receives a pointer to a string, and returns an int representation of the string.
for example: turns the string "432" to an int 432.
I am trying to convert string from 'ascii' to 'utf-8', the 'lencoded_str' function will take a pointer char and return another pointer char. the input pointer char size is unknown, and it will change each time the 'lencoded_str' function called. my problem is the 'lencoded_str' function always return nothing.
Any help would be much appreciated.
this is just an example
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iconv.h>
char *lencoded_str(char *in_str){
iconv_t iconv_obj = iconv_open("utf-8","ascii");
char *out_str = calloc(strlen(in_str) * 2, sizeof(char));
char *out_str_start = out_str;
size_t in_str_bytes_left = strlen(in_str);
size_t out_str_bytes_left = strlen(in_str) * 2;
int iconv_return = iconv(iconv_obj, &in_str, &in_str_bytes_left, &out_str, &out_str_bytes_left);
iconv_close(iconv_obj);
return out_str;
}
int main( ){
printf("out: %s\n", lencoded_str("123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"));
printf("out: %s\n", lencoded_str("123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"));
printf("out: %s\n", lencoded_str("123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"));
}
iconv advances toe input and output string pointers so that they point at the end of the converted string.
That means you must save the original value of the char buffer and return it. You've already had the right idea with out_str_start, but you don't use it:
return out_str_start;
By using the return value from lencoded_str directly in printf and not storing it, you will leak the memory that yopu calloced. You could also go easy on the strlens; you only need to call it once.
I am writing a program that stores information of the iwscan Ubuntu command. I am actually reading properly the file that is created with the information; however, when trying to store data(ESSID in a string, Channel in an int and Quality in a double), I have several problems treating the strings to extract the data...
The code is as following:
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
char *tratarEssid(char *cadena);
int tratarCanal(char *cadena);
double tratarCalidad(char *cadena);
int tratarCanal(char *cadena){
char resultado[2];
strncpy(resultado,cadena+9,2);
int canal;
canal=atoi(resultado);
return canal;
}
double tratarCalidad(char *cadena){
char resultado[6];
strncpy(resultado,cadena+8,6);
char num[2];
char den[2];
strncpy(num,resultado,2);
if(strlen(resultado)==5)
strncpy(den,resultado+3,2);
else
strncpy(den,resultado+2,2);
double numerador=atof(num);
double denominador=atof(den);
double calidad=numerador/denominador;
return calidad;
}
char *tratarEssid(char *cadena){
char *essid;
essid=(char *)malloc(sizeof(char)*10);
strncpy(essid,cadena+7,10);
return essid;
}
int main(){
int i;
const char *CHECKCANAL = "Channel:";
const char *CHECKQUALITY = "Quality=";
const char *CHECKESSID = "ESSID:";
double calidad;
int canal;
char *essid;
char cadena[20];
system("iwlist wlan0 scan | egrep \"(Channel|Signal level|ESSID)\">/home/wein/Escritorio/basic/bin/Debug/Lista.txt");
printf("Lista hecha\n");
lista=fopen("Lista.txt","r");
printf("Lista abierta\n");
while (!feof(lista)){
fgets(cadena,20,lista);
printf("%s",cadena);
if (strncmp(CHECKCANAL,cadena,strlen(CHECKCANAL))==0){
canal=tratarCanal(cadena);
printf("CANAL: %d\n",canal);
}
else if (strncmp(CHECKQUALITY,cadena,strlen(CHECKCANAL))==0){
calidad=tratarCalidad(cadena);
printf("CALIDAD: %f",calidad);
}
else if(strncmp(CHECKESSID,cadena,strlen(CHECKESSID))==0){
essid=tratarEssid(cadena);
printf("ESSID: %s\n",essid);
}
}
return 0;
}
So I know that my problem is in the conditionals made to filterig and treating the useful strings, just I don't know why the strncmp doesn't work properly (It should compare the beginning of the line with content of the String, or that's the idea) and thus, the functions don't work properly (Maybe I messed up in the functions as well...). Is there any other chance for treating the strings I receive correctly??
The output of the printf of the char[] cadena is just like this
Channel:11
Frequency:2.462 GH
z (Channel 11)
Quality=57/70 Sig
nal level=-53 dBm
ESSID:"eduroam"
And I should be able to extract from there the ESSID, Quality and Channel.
Thanks for any idea/suggestion/help received.
use strtok() on cadena[] to divide the string into tokens as,
token[0]=strtok(cadena,"\n") //considering the output you gave each date is in newline
token[1]=strtok(NULL,"\n")
token[2]=strtok(NULL,"\n")
token[3]=strtok(NULL,"\n")
token[4]=strtok(NULL,"\n")
token[5]=strtok(NULL,"\n")
then use sscanf() to get the required data from the token as,
sscanf(token[5],"ESSID:%s",ESSID);
sscanf(token[3],"Quality=%d/%d",&q1,&q2 ) //quality=q1/q2
sscanf(token[0],"Channel:%d",&channel)
this will give the required values from the string cadena[].
Your strncpy function calls don't add the terminator to the strings you copy to. Besides, they are to small to contain the terminator.
That means that when you call functions such as atoi on an unterminated string it will cause undefined behavior, as the function continues beyond the end of the allocated memory.