Pointers and dynamic memory allocation in c - c

im reading lines from an input text file and i'm storing the lines in an array array1
once im done reading id like to print out the elements in the array.. id like to do dynamic memory allocation.. but thats after i get this part working..
my code so far:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LEN 256
int main(){
FILE* fp;
fp=fopen("input.txt","r");
char currentline[MAX_LEN];
int i=0;
char *array1;
array1 = malloc(10*MAX_LEN);
while(fgets(currentline,MAX_LEN,fp)!=NULL && i<10){
strcpy((char *)&array1[i],currentline);
printf("%s\n",currentline);
printf("array1= %s\n",(&array1[i]));
i++;
}
for (;i>=0;i--){
printf("%s\n",(&array1[i]));
}
}
input1.txt
101
84
65
13
hello
90
24
94
73
70
68
94
65
output:
101
array1= 101
84
array1= 84
65
array1= 65
13
array1= 13
hello
array1= hello
90
array1= 90
24
array1= 24
94
array1= 94
73
array1= 73
70
array1= 70
0
70
770
9770
29770
929770
h929770
1h929770
61h929770
861h929770
1861h929770
what i want it to do is print out each element..but its printing the first character of each line.. whats causing this?

In this line:
strcpy((char *)&array1[i],currentline);
you copy currentline to the to the array1, starting at its i-th element.
So basically you first copy currentLine starting at array[0], then leave first element and copy next currentLine starting at array[1] and so on. Every time you overwrite previous currentLine except its first element.
What you want (I suppose) to do is:
strcpy(&array1[i*MAX_LEN],currentline);
which will save every currentLine in its own block of 256 characters.
For i=0 you will write starting at array[0],
for i=1 at array[256]...
Also drop those ugly (char *) casts, they are unnecessary in here.
You should check if malloc worked before dereferencing array1, too

Related

Why does my c code not add the correct null zero at the end like it is supposed to and keeps printing out code?

I do not know why my code does not seem to be working properly. I am reading from a file, and grabbing each line and from there I am using my own function to try and break down each of the lines and add them to character arrays in a structure and then add those structures to an array. But for whatever reason, when I am trying to indivudually print out the individual values for all of the information it keeps printing out all of it. From what I am seeing, for whatever reason even though my function strsub is supposed to add a '\0' at the end, it does not seem to be doing that. So every time I pass in the pointer to the begging of each of the character variables it does not stop until the end of the whole structure so it starts by printing out the whole string and then prints out less and less. Is that the problem that I really have or am I missing something else?
This is my code so far. I first just tried creating a struct and filling the array with each pass, but unfortunantly I had the same issue.
#define _CRT_SECURE_NO_WARNINGS // Since I want to strictly use ANSI C and not Microsoft C without getting the warning message, I'm adding this line of code before I include header files.
#include <stdio.h> // "#include" includes the contents of another file, commonly called header file, into the source code file.
#include <string.h>
#define MAX 100
FILE *fp, *csit;
void strsub(char buf[], char sub[], int start, int end);
void printArray(struct trainCartrain[]);
struct trainCar {
char car[10];
char type[2];
char weight[6];
char length[3];
char horsepower[3];
char numberInTrain[4];
};
int main() {
struct trainCar ar[7];
struct trainCar train;
// test and open input file and output file.;
if (!(fp = fopen("train.txt", "r"))) {
printf("train.txt could not be opened for input.");
exit(1);
}
if (!(csit = fopen("csit.txt", "w"))) {
printf("csit.txt could not be opened for output.");
exit(1);
}
int i = 0;
char buf[MAX];
while (!feof(fp)) {
fgets(buf, MAX, fp);
strsub(buf, train.car, 0, 9);
strsub(buf, train.type, 10, 11);
strsub(buf, train.weight, 12, 17);
strsub(buf, train.length, 18, 20);
strsub(buf, train.horsepower, 21, 23);
strsub(buf, train.numberInTrain, 24, 27);
printf("%s", train.car);
printf("%s", train.type);
ar[i] = train;
i++;
}
printArray(ar);
fclose(csit);
fclose(fp);
return 0;
}
void strsub(char buf[], char sub[], int start, int end) { //strsub () grabs a substring, sub, from a string, buf, given the start and end index within the string.
int i, j;
for (j = 0, i = start; i <= end; i++, j++) {
sub[j] = buf[i];
}
sub[j] = '\0';
//end with the null terminator character that signifies the end of a string.
}
My file is small and simple, textfile
Boxcar D 44000 55 16 45
Hopper B 23000 62 18 33
Tanker G 15000 45 30 12
Autocar A 30000 37 23 6
Livestock L 56500 50 18 19
Coalcar C 49300 53 22 100
Flatcar F 18000 66 15 25
and what it prints out is
Boxcar D 44000 55 16 45
D 44000 55 16 45
44000 55 16 45
55 16 45
16 45
45
Hopper B 23000 62 18 33
B 23000 62 18 33
23000 62 18 33
62 18 33
18 33
33
Tanker G 15000 45 30 12
G 15000 45 30 12
15000 45 30 12
45 30 12
30 12
12
Autocar A 30000 37 23 6
A 30000 37 23 6
30000 37 23 6
37 23 6
23 6
6
Livestock L 56500 50 18 19
L 56500 50 18 19
56500 50 18 19
50 18 19
18 19
19
Coalcar C 49300 53 22 100
Flatcar F 18000 66 15 25C 49300 53 22 100
Flatcar F 18000 66 15 2549300 53 22 100
Flatcar F 18000 66 15 2553 22 100
Flatcar F 18000 66 15 2522 100
Flatcar F 18000 66 15 25100
Flatcar F 18000 66 15 25Flatcar F 18000 66 15 25F 18000 66 15 2518000 66 15 2566 15 2515 2525
can someone please explain what I am doing wrong? I do have to use this function strsub for my class too.
I am just trying to get it to print out the individual charachter data and not the whole string each time. I think it is an issue with the terminating zero at the end and when I tried debugging it does not seem to be adding that for some reason. I don't know why though, if that is the problem.
strsub(buf, train.car, 0, 9); accesses train.car with index 0 till 9 in the loop and then index 10 outside, but that's already out of bounds for a char car[10];.
Solution:
Increase the size of all of your arrays by 1 to have space for the 0-terminator of the string.
Also have a look at Why is “while( !feof(file) )” always wrong? . It is not related to your problem, but you might run into that problem in the next minutes.
Instead of
while (!feof(fp)) {
fgets(buf, MAX, fp);
....
}
use
while (fgets(buf, MAX, fp)) {
....
}
You missed a space in void printArray(struct trainCartrain[]);. It should be void printArray(struct trainCar train[]); and moved to after the definition of struct trainCar.
You also have to #include <stdlib.h> to use exit(1);

Replacing multiple new lines in a file with just one

This function is supposed to search through a text file for the new line character. When it finds the newline character, it increments the newLine counter, and when there are more than 2 consecutive blank new lines, its suppose to squeeze all the blank lines into just one blank line.
In my code if there are 2 new lines it's suppose to get rid of them and squeeze them into one, for testing purposes I also have it printing "new line" when it reaches the newLine < 2 condition. Right now it prints new line for every new line, whether its blank or not, and its not getting rid of the extra new lines. What am I doing wrong?
EDIT: HERE IS MY FULL CODE
http://pastebin.com/bsD3b38a
So basically the program is suppose to concatenate two files together and than perform various operations on them, like what I'm trying to do which is get rid of multiple consecutive blank new lines.
So in order to execute it in cygwin I do
./a -s file1 file2
Its suppose to concatenate file1 and file2 together into a file called contents.txt and than get rid of the consecutive new lines and display them on my cygwin terminal (stdout). (the -s calls the function to get rid of the consecutive lines). The third and fourth arguments passed in (file1 and file2) are the two files its suppose to concatenate together into one file called contents.txt The squeeze_lines function than reads the contents.txt file and is suppose to squeeze new lines. You can see below for an example for the contents I put in file1.txt. file2.txt just has a bunch of words followed by empty new lines.
int newLine = 1;
int c;
if ((fileContents = fopen("fileContents.txt", "r")) == 0)
{
perror("fopen");
return 1;
}
while ((c = fgetc(fileContents)) != EOF)
{
if (c == '\n')
{
newLine++;
if (newLine < 2)
{
printf("new line");
putchar(c);
}
}
else
{
putchar(c);
newLine = 0;
}
}
The file the program reads in a .txt file with these contents. Its suppose to read the file, get rid of the leading, and consecutive new lines, and output the new formatted contents to stdout on my cywgin terminal.
/* hello world program */
#include <stdio.h>
tab
2tabs
Diagnosis
The logic looks correct if you have Unix line endings. If you have Windows CRLF line endings but are processing the file on Unix, you have a CR before each LF, and the CR resets newLine to zero, so you get the message for each newline.
This would explain what you're seeing.
It would also explain why everyone else is saying your logic is correct (it is — provided that the lines end with just LF and not CRLF) but you are seeing an unexpected result.
How to resolve it?
Fair question. One major option is to use dos2unix or an equivalent mechanism to convert the DOS file into a Unix file. There are many questions on the subject on SO.
If you don't need the CR ('\r' in C) characters at all, you can simply delete (not print, and not zero newLine) those.
If you need to preserve the CRLF line endings, you'll need to be a bit more careful. You'll have to record that you got a CR, then check that you get an LF, then print the pair, and then check whether you get any more CRLF sequences and suppress those, etc.
Working code — dupnl.c
This program only reads from standard input; this is more flexible than
only reading from a fixed file name. Learn to avoid writing code which
only works with one file name; it will save you lots of recompilation
over time. Th code handles Unix-style files with newlines ("\n") only
at the end; it also handles DOS files with CRLF ("\r\n") endings; and
it also handles (old style) Mac (Mac OS 9 and earlier) files with CR
("\r") line endings. In fact, it handes arbitrary interleavings of
the different line ending styles. If you want enforcement of a single
mode, you have to do some work to decide which mode, and then use an
appropriate subset of this code.
#include <stdio.h>
int main(void)
{
FILE *fp = stdin; // Instead of fopen()
int newLine = 1;
int c;
while ((c = fgetc(fp)) != EOF)
{
if (c == '\n')
{
/* Unix NL line ending */
if (newLine++ == 0)
putchar(c);
}
else if (c == '\r')
{
int c1 = fgetc(fp);
if (c1 == '\n')
{
/* DOS CRLF line ending */
if (newLine++ == 0)
{
putchar(c);
putchar(c1);
}
}
else
{
/* MAC CR line ending */
if (newLine++ == 0)
putchar(c);
if (c1 != EOF && c1 != '\r')
ungetc(c1, stdin);
}
}
else
{
putchar(c);
newLine = 0;
}
}
return 0;
}
Example run — inputs and outputs
$ cat test.unx
data long enough to be seen 1 - Unix
data long enough to be seen 2 - Unix
data long enough to be seen 3 - Unix
data long enough to be seen 4 - Unix
data long enough to be seen 5 - Unix
$ sed 's/Unix/DOS/g' test.unx | ule -d > test.dos
$ cat test.dos
data long enough to be seen 1 - DOS
data long enough to be seen 2 - DOS
data long enough to be seen 3 - DOS
data long enough to be seen 4 - DOS
data long enough to be seen 5 - DOS
$ sed 's/Unix/Mac/g' test.unx | ule -m > test.mac
$ cat test.mac
$ ta long enough to be seen 5 - Mac
$ odx test.mac
0x0000: 0D 0D 64 61 74 61 20 6C 6F 6E 67 20 65 6E 6F 75 ..data long enou
0x0010: 67 68 20 74 6F 20 62 65 20 73 65 65 6E 20 31 20 gh to be seen 1
0x0020: 2D 20 4D 61 63 0D 0D 64 61 74 61 20 6C 6F 6E 67 - Mac..data long
0x0030: 20 65 6E 6F 75 67 68 20 74 6F 20 62 65 20 73 65 enough to be se
0x0040: 65 6E 20 32 20 2D 20 4D 61 63 0D 64 61 74 61 20 en 2 - Mac.data
0x0050: 6C 6F 6E 67 20 65 6E 6F 75 67 68 20 74 6F 20 62 long enough to b
0x0060: 65 20 73 65 65 6E 20 33 20 2D 20 4D 61 63 0D 64 e seen 3 - Mac.d
0x0070: 61 74 61 20 6C 6F 6E 67 20 65 6E 6F 75 67 68 20 ata long enough
0x0080: 74 6F 20 62 65 20 73 65 65 6E 20 34 20 2D 20 4D to be seen 4 - M
0x0090: 61 63 0D 0D 0D 0D 64 61 74 61 20 6C 6F 6E 67 20 ac....data long
0x00A0: 65 6E 6F 75 67 68 20 74 6F 20 62 65 20 73 65 65 enough to be see
0x00B0: 6E 20 35 20 2D 20 4D 61 63 0D 0D 0D n 5 - Mac...
0x00BC:
$ dupnl < test.unx
data long enough to be seen 1 - Unix
data long enough to be seen 2 - Unix
data long enough to be seen 3 - Unix
data long enough to be seen 4 - Unix
data long enough to be seen 5 - Unix
$ dupnl < test.dos
data long enough to be seen 1 - DOS
data long enough to be seen 2 - DOS
data long enough to be seen 3 - DOS
data long enough to be seen 4 - DOS
data long enough to be seen 5 - DOS
$ dupnl < test.mac
$ ta long enough to be seen 5 - Mac
$ dupnl < test.mac | odx
0x0000: 64 61 74 61 20 6C 6F 6E 67 20 65 6E 6F 75 67 68 data long enough
0x0010: 20 74 6F 20 62 65 20 73 65 65 6E 20 31 20 2D 20 to be seen 1 -
0x0020: 4D 61 63 0D 64 61 74 61 20 6C 6F 6E 67 20 65 6E Mac.data long en
0x0030: 6F 75 67 68 20 74 6F 20 62 65 20 73 65 65 6E 20 ough to be seen
0x0040: 32 20 2D 20 4D 61 63 0D 64 61 74 61 20 6C 6F 6E 2 - Mac.data lon
0x0050: 67 20 65 6E 6F 75 67 68 20 74 6F 20 62 65 20 73 g enough to be s
0x0060: 65 65 6E 20 33 20 2D 20 4D 61 63 0D 64 61 74 61 een 3 - Mac.data
0x0070: 20 6C 6F 6E 67 20 65 6E 6F 75 67 68 20 74 6F 20 long enough to
0x0080: 62 65 20 73 65 65 6E 20 34 20 2D 20 4D 61 63 0D be seen 4 - Mac.
0x0090: 64 61 74 61 20 6C 6F 6E 67 20 65 6E 6F 75 67 68 data long enough
0x00A0: 20 74 6F 20 62 65 20 73 65 65 6E 20 35 20 2D 20 to be seen 5 -
0x00B0: 4D 61 63 0D Mac.
0x00B4:
$
The lines starting $ ta are where the prompt overwrites the previous output (and the 'long enough to be seen' part is because my prompt is normally longer than just $).
odx is a hex dump program. ule is for 'uniform line endings' and analyzes or transforms data so it has uniform line endings.
Usage: ule [-cdhmnsuzV] [file ...]
-c Check line endings (default)
-d Convert to DOS (CRLF) line endings
-h Print this help and exit
-m Convert to MAC (CR) line endings
-n Ensure line ending at end of file
-s Write output to standard output (default)
-u Convert to Unix (LF) line endings
-z Check for zero (null) bytes
-V Print version information and exit
What the sample code resolved is:
1) squeeze the consecutive a few '\n' to just one '\n'
2) Get rid the leading '\n' at the beginning if there is any.
input: '\n\n\naa\nbb\n\ncc'
output: aa'\n'
bb'\n' //notice, there is no blank line here
cc
If it was the aim, then your code logic is correct for it.
By defining newLine = 1 , it will get rid of any leading '\n' of the
input txt.
And when there is a remained '\n' after processing, it will output a new line to give a hint.
Back to the question itself, if the actual aim is to squeeze consecutive blank lines to just one blank line(which needs two consecutive '\n', one for terminate previous line, one for blank line).
1) Let's confirm the input and expected output firstly,
Input text:
aaa'\n' //1st line, there is a '\n' append to 'aaa'
'\n' //2nd line, blank line
bbb'\n' //3rd line, there is a '\n' append to 'bbb'
'\n' //4th line, blank line
'\n' //5th line, blank line
'\n' //6th line, blank line
ccc //7th line,
Expected Output text:
aaa'\n' //1st line, there is a '\n' append to 'aaa'
'\n' //2nd line, blank line
bbb'\n' //3rd line, there is a '\n' append to 'bbb'
'\n' //4th line, blank line
ccc //5th line,
2) If it is the exact program target as above,then
if (c == '\n')
{
newLine++;
if (newLine < 3) // here should be 3 to print '\n' twice,
// one for 'aaa\n', one for blank line
{
//printf("new line");
putchar(c);
}
}
3) If you have to process the Windows format file(with \r\n ending) under Cygwin, then you could do as follows
while ((c = fgetc(fileContents)) != EOF)
{
if ( c == '\r') continue;// add this line to discard possible '\r'
if (c == '\n')
{
newLine++;
if (newLine < 3) //here should be 3 to print '\n' twice
{
printf("new line");
putchar(c);
}
}
else
{
putchar(c);
newLine = 0;
}
}
[EDITED]
The minimal change is:
if ( newLine <= 2)
forgive me and forget the previous code.
a slightly simpler alternative:
int c;
int duplicates=0;
while ((c = fgetc(fileContents)) != EOF)
{
if (c == '\n') {
if (duplicates > 1) continue;
duplicates++;
}
else {
duplicates=0;
}
putchar(c);
}
Dry ran the code:
If file starts with a newline character and newLine is 1:
For the first iteration:
if (c == '\n') //Will be evaluated as true for a new-line character.
{
newLine++; //newLine becomes 2 before next if condition is evaluated.
if (newLine < 2) //False, since newLine is not less than 2, but equal.
{
printf("new line");
putchar(c);
}
}
else //Not entered
{
putchar(c);
newLine = 0;
}
On the second iteration: (Assume that it is a consecutive newline char case)
if (c == '\n') //Will be evaluated as true for a new-line character.
{
newLine++; //newLine becomes 3 before next if condition is evaluated.
if (newLine < 2) //False, since newLine is greater than 2.
{
printf("new line");
putchar(c);
}
}
else //Not entered
{
putchar(c);
newLine = 0;
}
So,
Initialize newLine to 0.
if newline > 2
That should be greater than or equal to if you want to get rid of the second line.
Also you have newline strarting at one, then being incremented to two then reset to zero. Instead I recommend replacing the count with a boolean like
boolean firstNewlineFound = false
Then Whenever you find a newline set it to true; whenever it is true, delete onenewline and set it back to false.

C - how to fix to work printf in this code?

I'm C begginer.I'm making typing practice program for practice.
In line 42,it doesn't work printf.I want print rand_n.
I think it maybe array problem but i can't fix this code.
can you help me?
Thanks.Have a good day!
1 #include <stdio.h>
2 #include <time.h>
3 #include <string.h>
4 #include "getch.h"
5
6 int main()
7 {
8 char se[5][6][100]={{"AND THEN THERE WERE NONE", ....
27 ..... ," Young Lord L had surrendered to Cupid at last"}};
28
29
30 char mysent;
31 int accu=0,pro=0;
32 int rand_n;
33 double typing=0.0;
34 srand(time(NULL));
35 rand_n=rand()%1000;
36 time_t start=0,end=0;
37 typing = accu*60.00/(end-start);
38
39
40 printf(">> typing practice <<\n");
41 printf("accuracy : %d%% typing_pre_sec : %d\n",accu,typing);
42 printf("%s\n",se[rand_n]);
se is a 3D array of character. Or a 2D array of strings. You are indexing it only once, so se[rand_n] is actually an array of strings. You probably don't want it to be a 3D array in the first place. Remove [5] from the declaration.
Also, rand_n can be anywhere between 0 and 999. You probably want to do rand() % 5 or something.

bufbomb stack overflow failed

I'm using bufbomb.c to do some buffer overflow attack experimenting.
I successfully used gdb to debug the code. Howeverer; when I run the program directly, I get a "Segmentation fault (core dumped)" when I enter the characters to try the attack.
I used gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1. to build the following.
//bufbomb.c
/* Bomb program that is solved using a buffer overflow attack */
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
/* Like gets, except that characters are typed as pairs of hex digits.
Nondigit characters are ignored. Stops when encounters newline */
char *getxs(char *dest)
{
int c;
int even =1; /* Have read even number of digits */
int otherd =0; /* Other hex digit of pair */
char*sp = dest;
while ((c = getchar()) != EOF && c !='\n') {
if (isxdigit(c)) {
int val;
if ('0'<= c && c <='9')
val = c -'0';
else if ('A'<= c && c <='F')
val = c -'A'+10;
else
val = c -'a'+10;
if (even) {
otherd = val;
even =0;
}
else {
*sp++= otherd *16+ val;
even =1;
}
}
}
*sp++='\0';
return dest;
}
/* $begin getbuf-c */
int getbuf()
{
char buf[12];
getxs(buf);
return 1;
}
void test()
{
int val;
printf("Type Hex string:");
val = getbuf();
printf("getbuf returned 0x%x\n", val);
}
/* $end getbuf-c */
int main()
{
int buf[16];
/* This little hack is an attempt to get the stack to be in a
stable position
*/
int offset = (((int) buf) &0xFFF);
int*space = (int*) alloca(offset);
*space =0; /* So that don't get complaint of unused variable */
test();
return 0;
}
Then I executed it under gdb:
...> gdb ./bugbomb
...
..run
Type Hex string:30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 d8 bf ff ff 9f 85 04 08 b0 86 04 08 30 31 32 33 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 ef be ad de
getbuf returned 0xdeadbeef
[Inferior 1 (process 13530) exited normally]
And then without gdb::
./bufbomb
Type Hex string:30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 d8 bf ff ff 9f 85 04 08 b0 86 04 08 30 31 32 33 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 ef be ad de
Segmentation fault (core dumped)
I am looking for some help to resolve the seg-fault.
Run it under gdb with a bigger buffer to see which address it's trying to access to guess the stack offset of the return address used by getbuf().
To bear with small differences in memory offsets that arise from the use of gdb, use a NOP-sled. Your attack buffer should look like this:
|RET ADDRESS x 30 | NOPS (0x90) x 1000 | SHELLCODE|.
The return address should point to the middle of the NOP-sled.
If the execution jumps anywhere in the sled, it will slide to the shellcode.
You are accessing memory that your process doesn't "own".
When you run gdb, the compiler adds stuff (like extra debug info).
You can bypass the segmentation fault by expanding the stack before you attempt the buffer overflow:
int expand_stack(int n_bytes)
{
char buf[n_bytes];
return buf[n_bytes-1]; // access the memory to make sure the optimiser doesn't remove buf.
}
And in main, add a call to expand_stack before you call test:
int main()
{
int buf[16];
/* This little hack is an attempt to get the stack to be in a
stable position
*/
int offset = (((int) buf) &0xFFF);
int*space = (int*) alloca(offset);
*space = expand_stack(200);
test();
return 0;
}
Note that your code still invokes undefined behaviour.
Note2: If your compiler doesn't support variable length arrays, just use a fixed array, buf[200].

Accessing individual bytes in an array

I'm trying to access individual bytes of a wide-char array so that I can send it via winsock, and this is what I've got so far:
WCHAR* buffer_in_bytes = (WCHAR*)msc->wcArray;
unsigned char l;
for (unsigned int i = 0; i <= (msc->bSize*2); i++ )
{
l = (unsigned char)(*(buffer_in_bytes +i));
char s[256] ;
_itoa(l,s,16);
OutputDebugString(s);
}
They array contains a series of a(s) (aaaaaaaaaaaaaaaaaaaa....), and I would expect to see 00 61 00 61 00 61 as a result I get 61 61 61 61 61 61
Any ideas why?
Each element contains an 'a', or ASCII 61, which is what you see printed. I don't know why you would expect to see these interspersed with 0's.

Resources