Input integers from CSV file( graph adjacency list) in C - c

I'm trying to implement the BFS algorithm to determine the shortest path between two nodes.For that I have been given the graph as an input csv file which is the adjacency list.I plan to store this list as an array of struct "rel" and get input from the file shown in the code.However, the output doesn't show the correct values.
#include<stdlib.h>
#include<stdio.h>
typedef struct relation // to store the pair of integers in a csv file line (c connected to y
{
int x;
int y;
}rel; // relation
void split(char* buffer,char* string1,char* string2) // spilts buffer into two strings seperated by ,
{
char* buffer_trav = buffer; // trav ptr in buffer
char* string_trav = string1; // trav ptr to string 1 or 2(after ',' is read)
while(*buffer_trav!='\0')
{
if(*buffer_trav==',')
{
string_trav = string2;
buffer_trav+=1;
}
else
{
*string_trav = *buffer_trav;
string_trav+=1;
buffer_trav+=1;
}
}
}
int main(void)
{
FILE* fp = fopen("graph.csv","r"); // reading csv file
int max_number_data = 100; // maximum number of edge relations in the file
rel graph[max_number_data];
for(int i=0;i<max_number_data;i++)
{
graph[i].x=1 ;
graph[i].y=-1 ; // setting initial value to be used as a check point for other functions
}
char buffer[10];//buffer for input
char x_buffer[5];// buffer for name
char y_buffer[5]; // buffer for password
int count=0;
while(fgets(buffer,10,fp)!=NULL)
{
char* ptr; // to be used to convert string to integer;
split(buffer,x_buffer,y_buffer); // splits into two strings
printf("%s : %s;\n",x_buffer,y_buffer); // To debug
graph[count].x = (int)strtol(x_buffer,&ptr,10); // converts string to longint which is later cat into int
graph[count].y = (int)strtol(y_buffer,&ptr,10); // " " " " " " " " " " " " "" " " " " "" " "" "" " " ""
count++;
}
fclose(fp);
}
Input file:
0,1
0,2
0,3
0,4
0,5
0,6
0,7
0,8
0,10
0,11
0,12
0,13
0,17
0,19
0,21
0,31
1,0
1,2
1,3
1,7
1,13
1,17
1,19
1,21
1,30
2,0
2,1
2,3
2,7
2,8
2,9
2,13
2,27
2,28
2,32
3,0
3,1
3,2
3,7
3,12
3,13
4,0
4,6
4,10
5,0
5,6
5,10
5,16
6,0
6,4
6,5
6,16
7,0
7,1
7,2
7,3
8,0
8,2
8,30
8,32
8,33
9,2
9,33
10,0
10,4
10,5
11,0
12,0
12,3
13,0
13,1
13,2
13,3
13,33
14,32
14,33
15,32
15,33
16,5
16,6
17,0
17,1
18,32
18,33
19,0
19,1
19,33
20,32
20,33
21,0
21,1
22,32
22,33
23,25
23,27
23,29
23,32
23,33
24,25
24,27
24,31
25,23
25,24
25,31
26,29
26,33
27,2
27,23
27,24
27,33
28,2
28,31
28,33
29,23
29,26
29,32
29,33
30,1
30,8
30,32
30,33
31,0
31,24
31,25
31,28
31,32
31,33
32,2
32,8
32,14
32,15
32,18
32,20
32,22
32,23
32,29
32,30
32,31
32,33
33,8
33,9
33,13
33,14
33,15
33,18
33,19
33,20
33,22
33,23
33,26
33,27
33,28
33,29
33,30
33,31
33,32
The output( Debugging ) I get is:
0`#?d : 1
;
0`#?d : 2
;
0`#?d : 3
;
0`#?d : 4
;
0`#?d : 5
;
0`#?d : 6
;
0`#?d : 7
;
0`#?d : 8
;
0`#?d : 10
;
0`#?d : 11
;
0`#?d : 12
;
0`#?d : 13
;
0`#?d : 17
;
0`#?d : 19
;
0`#?d : 21
;
0`#?d : 31
;
1`#?d : 0
;
1`#?d : 2
;
1`#?d : 3
;
1`#?d : 7
;
1`#?d : 13
;
1`#?d : 17
;
1`#?d : 19
;
1`#?d : 21
;
1`#?d : 30
;
2`#?d : 0
;
2`#?d : 1
;
2`#?d : 3
;
2`#?d : 7
;
2`#?d : 8
;
2`#?d : 9
;
2`#?d : 13
;
2`#?d : 27
;
2`#?d : 28
;
2`#?d : 32
;
3`#?d : 0
;
3`#?d : 1
;
3`#?d : 2
;
3`#?d : 7
;
3`#?d : 12
;
3`#?d : 13
;
4`#?d : 0
;
4`#?d : 6
;
4`#?d : 10
;
5`#?d : 0
;
5`#?d : 6
;
5`#?d : 10
;
5`#?d : 16
;
6`#?d : 0
;
6`#?d : 4
;
6`#?d : 5
;
6`#?d : 16
;
7`#?d : 0
;
7`#?d : 1
;
7`#?d : 2
;
7`#?d : 3
;
8`#?d : 0
;
8`#?d : 2
;
8`#?d : 30
;
8`#?d : 32
;
8`#?d : 33
;
9`#?d : 2
;
9`#?d : 33
;
10#?d : 0
;
10#?d : 4
;
10#?d : 5
;
11#?d : 0
;
12#?d : 0
;
12#?d : 3
;
13#?d : 0
;
13#?d : 1
;
13#?d : 2
;
13#?d : 3
;
13#?d : 33
;
14#?d : 32
;
14#?d : 33
;
15#?d : 32
;
15#?d : 33
;
16#?d : 5
;
16#?d : 6
;
17#?d : 0
;
17#?d : 1
;
18#?d : 32
;
18#?d : 33
;
19#?d : 0
;
19#?d : 1
;
19#?d : 33
;
20#?d : 32
;
20#?d : 33
;
21#?d : 0
;
21#?d : 1
;
22#?d : 32
;
22#?d : 33
;
23#?d : 25
;
23#?d : 27
;
23#?d : 29
;
23#?d : 32
;
23#?d : 33
;
24#?d : 25
;
24#?d : 27
;
24#?d : 31
;
25#?d : 23
;
25#?d : 24
;
zsh: segmentation fault ./a.out

The issue was that strings were not terminated with null characters.Also, the segmentation fault occurred because while the csv file had around 200 lines, I initiated maximum input lines to 100.

Related

How to get the value of a variable in dwarf?

I am parsing dwarf files, and I want to get the value of a variable or a pointer.
For example,
#include<stdio.h>
int main(){
int *a=malloc(4*sizeof(int));
a[0]=1;
int *b=&a;
int c=a[0];
return 0;
}
I got the dwarf debug information like this:
<2><304>: Abbrev Number: 17 (DW_TAG_variable)
<305> DW_AT_name : a
<307> DW_AT_decl_file : 1
<308> DW_AT_decl_line : 4
<309> DW_AT_decl_column : 10
<30a> DW_AT_type : <0x341>
<30e> DW_AT_location : 2 byte block: 91 58 (DW_OP_fbreg: -40)
<2><311>: Abbrev Number: 18 (DW_TAG_subprogram)
<312> DW_AT_external : 1
<312> DW_AT_name : (indirect string, offset: 0x3f): malloc
<316> DW_AT_decl_file : 8
<317> DW_AT_decl_line : 0
<318> DW_AT_prototyped : 1
<318> DW_AT_type : <0x47>
<31c> DW_AT_declaration : 1
<31c> DW_AT_sibling : <0x326>
<3><320>: Abbrev Number: 19 (DW_TAG_formal_parameter)
<321> DW_AT_type : <0x39>
<3><325>: Abbrev Number: 0
<2><326>: Abbrev Number: 17 (DW_TAG_variable)
<327> DW_AT_name : b
<329> DW_AT_decl_file : 1
<32a> DW_AT_decl_line : 7
<32b> DW_AT_decl_column : 10
<32c> DW_AT_type : <0x341>
<330> DW_AT_location : 2 byte block: 91 60 (DW_OP_fbreg: -32) [without DW_AT_frame_base]
<2><333>: Abbrev Number: 17 (DW_TAG_variable)
<334> DW_AT_name : c
<336> DW_AT_decl_file : 1
<337> DW_AT_decl_line : 8
<338> DW_AT_decl_column : 9
<339> DW_AT_type : <0x65>
<33d> DW_AT_location : 2 byte block: 91 54 (DW_OP_fbreg: -44) [without DW_AT_frame_base]
I get the name,type,frame base offset of a,b and c, but could I know the value of int *b and int c ?

In C, I need some help fixing my code to read the frequency of each character in a file, and display it on screen

So I have written a code up in C to print the frequency of every character in a file called "harrypotter1.txt" (the whole first Harry Potter book). It works to the extent that there are random blank spaces printed with " : 0" next to it when it Should only print the character in the file. Below I will list my code, and show the output it prints on to the screen, If someone can help me fix the problem. NOTE: I need to use the struct!
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
struct pair //struct to store frequency and value
{
int frequency;
char value;
};
int main()
{
struct pair table[128]; //set to 128 because these are the main characters
int fd; // file descriptor for opening file
char buffer[1]; // buffer for reading through files bytes
fd = open("harrypotter1.txt", O_RDONLY); // open a file in read mode
for(int j = 0; j < 128; j++)//for loop to initialize the array of pair (struct)
{
table[j].value = j; // table with index j sets the struct char value to equal the index
table[j].frequency = 0; // then the table will initialize the frequency to be 0
}
while((read(fd, buffer, 1)) > 0) // read each character and count frequency
{
int k = buffer[0]; //index k is equal to buffer[0] with integer mask becasue each letter has a ASCII number.
table[k].frequency++; //using the struct pair table with index k to count the frequency of each character in text file
}
close(fd); // close the file
for (int i = 0; i < 128; i++) // use for loop to print frequency of characters
{
printf("%c: %d\n",table[i].value, table[i].frequency); // print characters and its frequency
}
return 0; //end of code
}
Output:
: 0
: 0
: 0
: 0
: 0
: 0
: 0
: 0
: 0
: 3
: 10702
: 0
: 0
: 10702
: 0
: 0
: 0
: 0
: 0
: 0
: 0
: 0
: 0
: 0
: 0
: 0
: 0
0
: 0
: 0
: 0
: 0
: 70803
!: 474
": 4758
#: 0
$: 0
%: 0
&: 0
': 3141
(: 30
): 33
*: 2
+: 0
,: 5658
-: 1990
.: 6136
/: 0
0: 5
1: 11
2: 3
3: 8
4: 6
5: 2
6: 1
7: 4
8: 1
9: 4
:: 69
;: 135
<: 0
=: 0
>: 0
?: 754
#: 0
A: 703
B: 348
C: 293
D: 685
E: 287
F: 426
G: 492
H: 2996
I: 1393
J: 51
K: 79
L: 209
M: 665
N: 488
O: 332
P: 639
Q: 203
R: 660
S: 844
T: 1055
U: 193
V: 192
W: 653
X: 2
Y: 326
Z: 5
[: 0
\: 1
]: 0
^: 0
_: 0
`: 0
a: 25887
b: 4980
c: 6403
d: 15932
e: 39628
f: 6431
g: 8127
h: 19535
i: 19422
j: 319
k: 3930
l: 14385
m: 6729
n: 21337
o: 25809
p: 4909
q: 217
r: 20990
s: 18870
t: 27993
u: 9562
v: 2716
w: 7744
x: 381
y: 8293
z: 259
{: 0
|: 0
}: 0
~: 1
: 0
*/
The C answer by Allan Wind is good insofar as it produces the correct results, but it does allocate a larger array of characters than the minimum needed to solve the problem. This waste of space is a compromise forced by the fact that C array indices must start at 0 and the first printable character ' ' has a value of 32 and the last printable character '~' has a value of 126.
with Ada.Text_IO; use Ada.Text_IO;
procedure count_graphic_characters is
subtype graphix is Character range ' ' .. '~';
counts : array (graphix) of Natural := (Others => 0);
The_file : File_Type;
C : Character;
begin
Open
(File => The_file, Mode => In_File,
Name => "src\count_graphic_characters.adb");
while not End_Of_File (The_file) loop
Get (File => The_file, Item => C);
counts (C) := counts (C) + 1;
end loop;
Close (The_file);
for I in counts'Range loop
Put_Line (I & ": " & counts (I)'Image);
end loop;
end count_graphic_characters;
This program counts the frequency of characters in its own source file using the Ada programming language.
The subtype graphix is defined to contain all the graphic characters starting at ' ' and ending at '~'. The array name counts is indexed by the characters in the subtype graphix. Each element of the array is an instance of the pre-defined subtype Natural, and is initialized to 0. The array contains exactly enough elements to count every graphic character in the source file.
The program will raise an exception if the file named in the Open procedure cannot be found.
As each character is read from the file that character is used as an index into the counts array and the corresponding element is incremented.
No space is wasted by creating a 128 element array. Instead an array of 95 characters is used. There is also no need to check each array element to determine if the character represented by the index is a printable character since the array index values are only the printable characters.
The output of this program is:
: 132
!: 0
": 4
#: 0
$: 0
%: 0
&: 2
': 6
(: 10
): 10
*: 0
+: 1
,: 3
-: 0
.: 5
/: 0
0: 1
1: 1
2: 0
3: 0
4: 0
5: 0
6: 0
7: 0
8: 0
9: 0
:: 6
;: 14
<: 0
=: 8
>: 6
?: 0
#: 0
A: 2
B: 0
C: 7
D: 0
E: 1
F: 5
G: 1
H: 0
I: 8
J: 0
K: 0
L: 1
M: 1
N: 2
O: 5
P: 1
Q: 0
R: 1
S: 0
T: 8
U: 0
V: 0
W: 0
X: 0
Y: 0
Z: 0
[: 0
\: 1
]: 0
^: 0
_: 18
`: 0
a: 26
b: 3
c: 21
d: 9
e: 43
f: 8
g: 9
h: 18
i: 22
j: 0
k: 0
l: 17
m: 3
n: 20
o: 22
p: 13
q: 0
r: 24
s: 15
t: 23
u: 13
v: 0
w: 2
x: 4
y: 3
z: 0
{: 0
|: 0
}: 0
~: 1
You can use an array instead of the struct as the value is simply the array index: table[j].value = j;. Initialized the array instead of assigning the initial values in a loop. Added error checking for open. Use isprint() to figure out if we should print a given character:
#include <ctype.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
// assumes 2^i to make the bitwise & work below
#define LEN 128
int main() {
unsigned frequency[LEN] = { 0 };
int fd = open("harrypotter1.txt", O_RDONLY);
if(fd == -1) {
printf("%s\n", strerror(errno));
return 1;
}
unsigned char buffer;
while((read(fd, &buffer, 1)) > 0) {
frequency[buffer & (LEN-1)]++;
}
close(fd);
for (int i = 0; i < LEN; i++) {
if(isprint(i))
printf("%c: %u\n", i, frequency[i]);
}
return 0;
}
and using the placing the content "hello world" in the input file, I get the following output:
: 1
!: 0
": 0
#: 0
$: 0
%: 0
&: 0
': 0
(: 0
): 0
*: 0
+: 0
,: 0
-: 0
.: 0
/: 0
0: 0
1: 0
2: 0
3: 0
4: 0
5: 0
6: 0
7: 0
8: 0
9: 0
:: 0
;: 0
<: 0
=: 0
>: 0
?: 0
#: 0
A: 0
B: 0
C: 0
D: 0
E: 0
F: 0
G: 0
H: 0
I: 0
J: 0
K: 0
L: 0
M: 0
N: 0
O: 0
P: 0
Q: 0
R: 0
S: 0
T: 0
U: 0
V: 0
W: 0
X: 0
Y: 0
Z: 0
[: 0
\: 0
]: 0
^: 0
_: 0
`: 0
a: 0
b: 0
c: 0
d: 1
e: 1
f: 0
g: 0
h: 1
i: 0
j: 0
k: 0
l: 3
m: 0
n: 0
o: 2
p: 0
q: 0
r: 1
s: 0
t: 0
u: 0
v: 0
w: 1
x: 0
y: 0
z: 0
{: 0
|: 0
}: 0
~: 0
The first 32 ASCII characters (values 0 - 31) are "non-printable" in the sense that they represent characters with special meaning or behavior. You can have your code as it is, but limit the actual print-out to only include "printable" characters. You could start at space ' ' (value 32) and end at 'z' (122) which will give most of the printables (though not just letters).
for (int i = ' '; i <= 'z'; i++) // use for loop to print frequency of characters
{
printf("%c: %d\n",table[i].value, table[i].frequency); // print characters and its frequency
}
From your printout one can see 10702 CR (value 13) and 10702 LF (value 10) revealing that the text file has 10702 newlines and is a Windows text file.

Remove empty content in array and sorted the array in C

I had face a problem which is I try to remove the content of the array which is zero and sort the array with value. Anyone has any suggestion on how to sorted the array ?
Let's say I got an array:
int array[10] = {1,2,513,0,4,5,6,0,0,9};
which I want convert to
array[10] = {1,2,513,4,5,6,9,0,0,0}
Any function to do that, with the least code require.
I would suspect had a very intelligent way to do that.
Again, please use the minimum code to handle this.
Thanks everyone
So, you don't want to sort your array after all ?
Well, this is the code to "remove" all the zero in an array.
Since you changed many time your question, I don't know if it will be the rigth answer.
If you have question, do not hesitate.
The algorithm used below is a commom algorithm : recopy the array with an offset.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void Array_Display(const int * const array, const size_t size)
{
for (size_t i = 0; i < size; ++i) {
printf("%d", array[i]);
if (i + 1 < size) {
printf(", ");
}
}
printf("\n");
}
void Array_MagicFunction(int * const array, size_t *size)
{
size_t j = 0;
for (size_t i = 0; i < *size; ++i) {
if (array[i] != 0) {
array[j] = array[i];
++j;
}
}
*size = j;
}
#define ARRAY_SIZE 10
int main(void)
{
int array[ARRAY_SIZE] = {1,2,513,0,4,5,6,0,0,9};
size_t size = ARRAY_SIZE;
Array_Display(array, size);
Array_MagicFunction(array, &size);
Array_Display(array, size);
return (EXIT_SUCCESS);
}
I keep my first answer in case you still want to sort your array.
----------
Edit : Attention please.
The provided code below doesn't work for Jackdon for some mysterious reasons.
It seem that his implementation of qsort is bugged (which is really surprising consedering a bug in a massive used function is higlhy improbable) : even when the function return the correct value, the array is not sorted ...
I don't understand what's going on, I'm pretty sure that my code is correct (and it work on Debian9), so I just put some poor "debugging".
Jackdon environment is the following :
Windows 10
Microsoft Visual Studio 2017 Community
the compile setting is follow default
Tom's To Jackdon :
Could you please replace the intcmp function with this ?
int intcmp(const void *first, const void *second)
{
const int *firstInt = first;
const int *secondInt = second;
int result;
if (*firstInt == 0) {
result = 1;
} else {
result = (*firstInt) - (*secondInt);
}
printf("POOR DEBUG : ");
for (size_t i = 0 ; i < ARRAY_SIZE; ++i) {
printf("%d ", array[i]);
}
printf("\ncomparing %d to %d : %d\n", *firstInt, *secondInt, result);
return (result);
}
Jackdon To Tom's
POOR DEBUG : 1 2 3 0 4 5 6 0 0 9
comparing 1 to 5 : -4
POOR DEBUG : 1 2 3 0 4 5 6 0 0 9
comparing 1 to 9 : -8
POOR DEBUG : 1 2 3 0 4 5 6 0 0 9
comparing 5 to 9 : -4
POOR DEBUG : 1 2 3 0 4 5 6 0 0 9
comparing 2 to 5 : -3
POOR DEBUG : 1 2 3 0 4 5 6 0 0 9
comparing 3 to 5 : -2
POOR DEBUG : 1 2 3 0 4 5 6 0 0 9
comparing 0 to 5 : 1
POOR DEBUG : 1 2 3 0 4 5 6 0 0 9
comparing 0 to 5 : 1
POOR DEBUG : 1 2 3 0 4 5 6 0 0 9
comparing 0 to 5 : 1
POOR DEBUG : 1 2 3 0 4 5 6 0 0 9
comparing 6 to 5 : 1
POOR DEBUG : 1 2 3 5 4 0 6 0 0 9
comparing 4 to 5 : -1
POOR DEBUG : 1 2 3 5 4 0 6 0 0 9
comparing 0 to 5 : 1
POOR DEBUG : 1 2 3 5 4 0 6 0 0 9
comparing 4 to 5 : -1
POOR DEBUG : 1 2 3 5 4 0 6 0 0 9
comparing 4 to 5 : -1
POOR DEBUG : 1 2 3 5 4 0 6 0 0 9
comparing 6 to 0 : 6
POOR DEBUG : 1 2 3 5 4 0 6 0 0 9
comparing 0 to 6 : 1
POOR DEBUG : 1 2 3 5 4 0 6 0 0 9
comparing 0 to 0 : 1
POOR DEBUG : 1 2 3 5 4 0 6 0 0 9
comparing 9 to 0 : 9
POOR DEBUG : 1 2 3 5 4 0 6 0 0 9
comparing 6 to 0 : 6
POOR DEBUG : 1 2 3 5 4 0 6 0 0 9
comparing 0 to 6 : 1
POOR DEBUG : 1 2 3 5 4 0 6 0 0 9
comparing 0 to 0 : 1
POOR DEBUG : 1 2 3 5 4 0 6 0 0 9
comparing 6 to 0 : 6
POOR DEBUG : 1 2 3 5 4 0 6 0 0 9
comparing 0 to 6 : 1
POOR DEBUG : 1 2 3 5 4 0 6 0 0 9
comparing 6 to 0 : 6
POOR DEBUG : 1 2 3 5 4 0 6 0 0 9
comparing 2 to 1 : 1
POOR DEBUG : 1 2 3 5 4 0 6 0 0 9
comparing 3 to 2 : 1
POOR DEBUG : 1 2 3 5 4 0 6 0 0 9
comparing 5 to 3 : 2
POOR DEBUG : 1 2 3 5 4 0 6 0 0 9
comparing 4 to 5 : -1
POOR DEBUG : 1 2 3 4 5 0 6 0 0 9
comparing 2 to 1 : 1
POOR DEBUG : 1 2 3 4 5 0 6 0 0 9
comparing 3 to 2 : 1
POOR DEBUG : 1 2 3 4 5 0 6 0 0 9
comparing 4 to 3 : 1
POOR DEBUG : 1 2 3 4 5 0 6 0 0 9
comparing 2 to 1 : 1
POOR DEBUG : 1 2 3 4 5 0 6 0 0 9
comparing 3 to 2 : 1
POOR DEBUG : 1 2 3 4 5 0 6 0 0 9
comparing 2 to 1 : 1
1 2 3 4 5 0 6 0 0 9
----------
Use qsort.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int intcmp(const void *first, const void *second)
{
const int *firstInt = first;
const int *secondInt = second;
if (*firstInt == 0) {
return (1);
}
return (*firstInt - *secondInt);
}
#define ARRAY_SIZE 10
int main(void)
{
int array[ARRAY_SIZE] = {1,2,3,0,4,5,6,0,0,9};
qsort(array, ARRAY_SIZE, sizeof(*array), intcmp);
for (size_t i = 0 ; i < ARRAY_SIZE; ++i) {
printf("%d ", array[i]);
}
printf("\n");
return (EXIT_SUCCESS);
}
The "removing zero" part is handled by putting all zero at the end of the array. So your final array length will simply be found by searching the index of the first zero in the array (don't forget to take care if there is no 0 is the array to begin with).

How to keep a column in a new array, based on numbers that exist in other column?

I have this matrix:
aux333=[2 0 ;
2 0 ;
2 0 ;
2 0 ;
2 0 ;
2 0 ;
2 0 ;
2 0 ;
2 0 ;
2 0 ;
2 0 ;
2 0 ;
2 0 ;
2 0 ;
2 0 ;
2 70 ;
3 0 ;
2 0 ;
2 0 ;
2 0 ;
2 0 ;
2 0 ;
2 0 ;
2 208;
2 0 ;
2 0 ;
2 0 ;
2 0 ;
2 0 ;
0 37 ;
0 0 ;
0 0 ;
0 0 ;
0 0 ]
and I want to write some code that, if the first column is different from zero, a new array (aux3final) will receive the second column of aux333.
I tried writing it like this:
for j=1:length(aux333)
if aux333(j,1)==2 | aux333(j,1)==3
aux3final(j)=aux333(j,2);%%aux3final tá com dimensão 296, devia estar com dimensão 69
end
but this isn't working at all. How to proceed?
The original code is bigger than what I posted, may be there is some variable influencing something.
As Sardar pointed out, it is not clear whether the resulting vector (aux3final) should have
1) the same length as the input vector(aux333)
%find entries of interest
flg_valid=aux333(:,1)>0;
%alloc output
aux3final=zeros(size(aux333,1),1);
%copy index depending
aux3final(flg_valid)=aux333(flg_valid,2);
or
2) it has the length of the entries of interest
%extract only entries of interest
aux3final=aux333(flg_valid,2);

How to make cipher more efficient

I have written the code for a rail fence cipher decoder, the input provided is the number of rails and the already encoded text. The decoder works, however, it only works for small inputs or short words. If i try entering a paragraph with a rails of 10 no output shows up.
I am still trying to grasp the concept of Order of a function, so I'm unsure of the order of my program. How do I make it more efficient or improve its efficiency?
Decrypt Function:
void decrypt(int rail,char *cipher) {
int length = strlen(cipher);
int i, j;
int counter=0,num=0,in=1;
int railfence[rail][100],count[100];
for(i=0;i < length;i++)
count[i]=0;
for(i=0;i < length;i++){
if(num + in == rail) in =- 1;
else if(num + in == -1)in = 1;
railfence[num][count[num]] = i;
++count[num];
num += in;
}
char buffer[1000];
for(i=0;i < rail;i++)
for(j=0;j < count[i];j++){
buffer[railfence[i][j]] = cipher[counter];
++counter;
}
buffer[length]='\0';
printf("%s\n",buffer);
}
Any help would be appreciated.
When your rail is larger than the message length, your have uninitialised string lengths for each rail. You initialise count in a loop from 0 to the message length, but you should initalise a length for each rail:
for (i = 0; i < rail; i++)
count[i] = 0;
That change should fix your error.
You are using variable-length arrays, and you know the size of these arrays. So there's no need to guess the dimensions (and make them large enough just in case). You can determine the lengths:
int zigzag[rail][length / (rail - 1) + 1];
int count[rail];
char buffer[length + 1];
(The zigzag array's inner rails have twice the number of letters in the two outer rails. Considering top and bottom rail as one, each rail must cater for at most length / (rail - 1) + 1. The + 1 at the end catches division cutoffs.)
The algorithm can probably be made more efficient by walking the message without an additional two-dimensional array. Traverse rail i with an alternating stride of 2 * (rail - 1 - i) and 2 * i. You must take care not to treat the letters of the top and bottom rails twice (when the stride is zero).
This should be considered a teaser for an optimal implementation:
if (rail == 0 || rail == railCount - 1) {
plaintextOffset = rail + offInRail * (iterfreq * 2);
} else {
if (offInRail % 2 == 0) {
plaintextOffset = rail + offInRail * iterfreq;
} else {
plaintextOffset = railCount - rail - 1 + offInRail * iterfreq;
}
}
You'll need to iterate over the rails, keeping the starting offset of the rail in the ciphertext in mind. Then you can iterate over the possible characters in the rail, while testing if plaintextOffset is not too high.
Example output using the Wikipedia plaintext as test vector:
Rails: 3, size 25
CT rail 0 : 0 + 0 = 0 <-> 0 PT
CT rail 0 : 0 + 1 = 1 <-> 4 PT
CT rail 0 : 0 + 2 = 2 <-> 8 PT
CT rail 0 : 0 + 3 = 3 <-> 12 PT
CT rail 0 : 0 + 4 = 4 <-> 16 PT
CT rail 0 : 0 + 5 = 5 <-> 20 PT
CT rail 0 : 0 + 6 = 6 <-> 24 PT
CT rail 0 : 7 + 7 = 14 <-> 28 PT (too high)
CT rail 1 : 7 + 0 = 7 <-> 1 PT
CT rail 1 : 7 + 1 = 8 <-> 3 PT
CT rail 1 : 7 + 2 = 9 <-> 5 PT
CT rail 1 : 7 + 3 = 10 <-> 7 PT
CT rail 1 : 7 + 4 = 11 <-> 9 PT
CT rail 1 : 7 + 5 = 12 <-> 11 PT
CT rail 1 : 7 + 6 = 13 <-> 13 PT
CT rail 1 : 7 + 7 = 14 <-> 15 PT
CT rail 1 : 7 + 8 = 15 <-> 17 PT
CT rail 1 : 7 + 9 = 16 <-> 19 PT
CT rail 1 : 7 + 10 = 17 <-> 21 PT
CT rail 1 : 7 + 11 = 18 <-> 23 PT
CT rail 1 : 19 + 12 = 31 <-> 25 PT (too high)
CT rail 2 : 19 + 0 = 19 <-> 2 PT
CT rail 2 : 19 + 1 = 20 <-> 6 PT
CT rail 2 : 19 + 2 = 21 <-> 10 PT
CT rail 2 : 19 + 3 = 22 <-> 14 PT
CT rail 2 : 19 + 4 = 23 <-> 18 PT
CT rail 2 : 19 + 5 = 24 <-> 22 PT
CT rail 2 : 25 + 6 = 31 <-> 26 PT (too high)
WECRLTEERDSOEEFEAOCAIVDEN
Rails: 3, size 25
CT rail 0 : 0 + 0 = 0 <-> 0 PT
CT rail 0 : 0 + 1 = 1 <-> 4 PT
CT rail 0 : 0 + 2 = 2 <-> 8 PT
CT rail 0 : 0 + 3 = 3 <-> 12 PT
CT rail 0 : 0 + 4 = 4 <-> 16 PT
CT rail 0 : 0 + 5 = 5 <-> 20 PT
CT rail 0 : 0 + 6 = 6 <-> 24 PT
CT rail 0 : 7 + 7 = 14 <-> 28 PT (too high)
CT rail 1 : 7 + 0 = 7 <-> 1 PT
CT rail 1 : 7 + 1 = 8 <-> 3 PT
CT rail 1 : 7 + 2 = 9 <-> 5 PT
CT rail 1 : 7 + 3 = 10 <-> 7 PT
CT rail 1 : 7 + 4 = 11 <-> 9 PT
CT rail 1 : 7 + 5 = 12 <-> 11 PT
CT rail 1 : 7 + 6 = 13 <-> 13 PT
CT rail 1 : 7 + 7 = 14 <-> 15 PT
CT rail 1 : 7 + 8 = 15 <-> 17 PT
CT rail 1 : 7 + 9 = 16 <-> 19 PT
CT rail 1 : 7 + 10 = 17 <-> 21 PT
CT rail 1 : 7 + 11 = 18 <-> 23 PT
CT rail 1 : 19 + 12 = 31 <-> 25 PT (too high)
CT rail 2 : 19 + 0 = 19 <-> 2 PT
CT rail 2 : 19 + 1 = 20 <-> 6 PT
CT rail 2 : 19 + 2 = 21 <-> 10 PT
CT rail 2 : 19 + 3 = 22 <-> 14 PT
CT rail 2 : 19 + 4 = 23 <-> 18 PT
CT rail 2 : 19 + 5 = 24 <-> 22 PT
CT rail 2 : 25 + 6 = 31 <-> 26 PT (too high)
WEAREDISCOVEREDFLEEATONCE
I'm not super familiar with the algorithm, but it seems like you could save a bunch of time and memory if first you found the length of the string, then found the number of spaces (possibly using this), subtracted those two numbers, and then divided by rail (let's call the resulting number numCols). Then you'd just create one 2D char array, with rail rows and numCols columns. Go through with two for loops (columns nested inside of the rows) inserting the characters in order (making sure to avoid spaces).
Once you've done that, just read them back out, except this time, nest your rows loop inside your columns loop.

Resources