I have some code that is trying to take in data from a file. the format is like this : 9/2d 0/1s. There could be multiple of those in the file but i need to take the first number and set it as the index to add at. Then I need to save the next number and character as separate values. I have some code here but it doesn't work so well.
struct matrix tokens[nbrState][12];
int *num = 0;
int index = 0;
while ((ptr = fgets(buf, 256, fp)) != NULL){
ptrToken = strtok(buf, "/");
int count = 0;
for(int r = 0; r < 12; r++){
if(count >= 3){
ptrToken = strtok(NULL, " ");
index = atoi(ptrToken);
tokens[index][r].state = index;
}
count++;
}
}
Here is my updated code. It works abit better.
struct matrix tokens[nbrState][12];
char *tok;
int index = 0;
int state = 0;
while((ptr = fgets(buf, 256, fp)) != NULL){
ptrToken = strtok(buf, " ");
tok = ptrToken;
//index = strtok(tok, "/");
for(int r = 0; r < 12; r++){
index = atoi(tok);
state = atoi(ptrToken);
tokens[index][12].state = state;
}
}
You could try this
while ( ( fscanf ( fp, "%d/%d%c", &index, &separateInt, &separateChar) == 3) {
// use values as needed
tokens[index][11].state = sepatateInt;
}
The loop will continue until EOF or input from the file does not match the format.
Related
void redact_words(const char *text_filename, const char *redact_words_filename){
FILE *fp = fopen(text_filename,"r");
FILE *f2p = fopen(redact_words_filename,"r");
FILE *f3p = fopen("result.txt", "w"); ;
char buffer1[1000];
char buffer2[1000];
char *word;
char *redact;
char **the_words;
//if ((fgets(buffer1, 1000 ,fp) == NULL) || (fgets(buffer2,1000 ,f2p) == NULL))
fgets(buffer1,1000,fp);
fgets(buffer2,1000,f2p);
rewind(fp);
rewind(f2p);
int word_count = 0;
while (!feof(f2p)){
char c = fgetc(f2p);
if (c == ' '){
word_count += 1;
}
}
word_count += 1;
the_words = malloc(3 * sizeof(char*));
redact = strtok(buffer2, ", ");
for (int i = 0; i < word_count; i++){
the_words[i] = malloc(100);
the_words[i] = redact;
redact = strtok(NULL, ", ");
}
char result[256] = "";
word = strtok(buffer1, " ");
while (word != NULL){
for (int i = 0; i < word_count; i++){
if (strcasecmp(the_words[i],word) == 0){
for (int i = 0; i < strlen(word); i++){
strcat(result,"*");
}
strcat(result, " ");
break;
}
else{
if (i==(word_count-1)){
strcat(result, word);
strcat(result, " ");
}
}
}
word = strtok(NULL," ");
}
fputs(result, f3p);
fclose(fp);
fclose(f2p);
fclose(f3p);
free(the_words);
}
So this is my C code to replace words from the file called text_filename with asterixs if the word exists in a file called redact_words_filename. However, I noticed during the comparison with the 2 strings
if (strcasecmp(the_words[i],word) == 0){
for (int i = 0; i < strlen(word); i++){
strcat(result,"*");
}
that when I have the word quick for example in both text files, the_words[i] contains a string of length 6 while the one in word contains a string of length 5, both containing the value quick, and so it is not registering as the same string. Why is one of the strings longer than another?
(P.s I apologise for the bad code quality)
Edit 1: Ok so I found out it has to do with \n which is put in at the end of every line. Trying to find a way to solve this.
Edit 2: I managed to get rid of \n through a simple for loop
for (int i = 0; i < word_count; i++){
the_words[i] = malloc(100);
the_words[i] = redact;
for (int j = 0; j < strlen(redact); j++){
if (redact[j] == '\n'){
redact[j] = '\0';
}
}
redact = strtok(NULL, ", ");
}
the_words = malloc(3 * sizeof(char*));
redact = strtok(buffer2, ", ");
for (int i = 0; i < word_count; i++){
the_words[i] = malloc(100);
the_words[i] = redact;
redact = strtok(NULL, ", ");
}
Two obvious problems just here
you allocate space for 3 pointers in the_words but then you go and put word_count words into it. So if word_count > 3, you'll overflow and get undefined behavior
for each word, you allocate 100 bytes, and then throw away that allocation, instead storing a pointer into buffer2. The buffer currently contains the word but that will change next time you read into it. You should just use the_words[i] = strdup(redact); to both allocate the right amount of memory, and copy the string into the allocated memory.
I am a beginner at coding and am currently in a course for this. I have been asked to produce a program that has a special function to convert the timestamps in a file into something that can be sorted from earliest to latest based on a numerical value. These would be imported from a file into an array. Some points of the assignment are:
The array of strings should be allocated dynamically to minimise the amount of memory used.
Create a function called timeStampToSeconds() that converts a timestamp string to a long int, which represents the number of seconds elapsed since 01/01/2000 00:00:00.
Your code will need to check that each character is a valid number between 0 and 9, ignoring formatting characters ('/', ' ', ':', '-') and convert the characters to their equivalent integers before being used to calculate the number of seconds elapsed since the above starting point.
I have included my code but am wondering if anyone has any pointers to help me on point 2 & 3? I have started with trying to implement point 3 with the strtok function, but I think I may be way off on this.Curently my function prototype is not doing what I had hoped for this.
Any advice would be much appreciated.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 50
void timeStampToSeconds(char array[]);
int main(void)
{
char array[50][20];
char input[10], filename[] = "Timestamps", outputfile[40], file_ext[4] = ".dat";
int i = 0, n = 0, j, x = 0, y = 0, o = 0;
double datetime = 0;
while (*input != *filename) {
printf("\nPlease enter the names of the required Input file: \n");
scanf("%s", input);
if (*input == *filename) {
printf("Input accepted!\n");
}
else printf("File name not found.Please try again!\n");
}
printf("Please enter the name of the sorted Output file to be created: \n");
scanf("%s", &outputfile);
strncat(&outputfile, &file_ext, 4); /*appends file extension characters to outputfile
variable characters*/
FILE* Ptr = NULL;
FILE* cfPtr = (char*)malloc(100 * sizeof(char));
if ((cfPtr = fopen("Timestamps.dat", "r")) == NULL) {
printf("File could not be opened\n");
}
while (!feof(cfPtr))
{
for (i = 0; i < 50; ++i)
{
for (j = 0; j < 20; ++j)
{
array[x][j] = fgetc(cfPtr);
y++;
}
x++;
}
}
fclose(cfPtr);
timeStampToSeconds(array);
if ((Ptr = fopen(outputfile, "w")) == NULL) {
printf("File could not be opened\n");
}
fwrite(array, sizeof(char), sizeof(array), Ptr);
fclose(Ptr);
return 0;
}
void timeStampToSeconds(char array[])
{
array;
long int n = 0, j = 0;
const char a[2] = "/"; const char b[2] = "-";
const char c[2] = ":";
char* token; char* token2; char *token3;
for (int i = 0; i < SIZE - 1; ++i) {
token = strtok(array, a);
while (token != NULL) {
token = strtok(NULL, a);
}
token2 = strtok(token, b);
while (token2 != NULL) {
token2 = strtok(NULL, b);
}
token3 = strtok(token2, c);
while (token3 != NULL) {
token3 = strtok(NULL, c);
}
token3 = array;
}
for (int i = 0; i < SIZE - 1; ++i) {
n = atol(array[i]);
array[i] = n;
}
}
I'm trying to get from user input a string with spaces for example "abcd12314 asdfg92743 ppoqws21321" and separate them and then store them in an array. But it gives me a segmentation fault
int main() {
char string[150];
int i = 0;
fgets(string, sizeof(string), stdin);
char *words = strtok(string, " ");
char *stored[150];
while (words != NULL) {
stored[i++] = words;
words = strtok(NULL, " ");
}
for (i = 0; i < strlen(string); i++) {
printf("%s\n", stored[i]);
}
return 0;
}
You want this:
int main() {
char string[150];
int i = 0;
fgets(string,sizeof(string),stdin);
char *words = strtok (string, " ");
char *stored[150];
while (words != NULL) {
stored[i++] = words;
words = strtok (NULL, " ");
}
int nbofwords = i; // <<<< add this
for (i = 0; i < nbofwords; i++) { // change this line
printf("%s\n", stored[i]);
}
return 0;
}
But this code is error prone, you should rather write it like below. You should declare variables upon first usage and declare loop counters directly in the for statement.
int main() {
char string[150];
fgets(string, sizeof(string), stdin);
char* stored[150];
int nbofwords = 0;
char* words = strtok(string, " ");
while (words != NULL) {
stored[nbofwords++] = words;
words = strtok(NULL, " ");
}
for (int i = 0; i < nbofwords; i++) {
printf("%s\n", stored[i]);
}
return 0;
}
Disclaimer: this is untested code.
I have tried to write a code for reading my CSV file and put the data in a 2D array. but when I run this code I see that all element of array are zero, kindly please help me to know what should I change?
int main(void){
int rowID = 0; //declare row index
int columnID = 0; //declare column index
int data_new[10000][5] = {{0, 0}}; //create the matrix that we want to put the data
char line[50000]; //size of array line
char token = NULL;
FILE *data_csv = fopen("data.csv", "r");
if (data_csv == NULL){
perror("unable to open the file");
exit(1);
}
while (fgets(line, 50000, data_csv))
{
columnID = 0;
rowID++;
if (rowID == 1)
{
continue;
} //to remove the headers
char *each_line = strtok(line, ", "); //this split the data by ,
each_line = strtok(NULL, ", ");
columnID++;
}
fclose(data_csv); // Close the file
for (int i = 0; i < rowID; ++i)
{
for (int j = 0; j < 5; ++j)
printf("%10.4lf", data_new[i][j]);
putchar('\n');
}
}
I am trying to write a simple program that will allow the user to extract data from a csv file after specifying what rows and columns they would like to extract. The program accepts inputs for the start row (can be any number, not necessarily 1) and the final row desired. The same principle applies for the columns. The output is then assigned to a multidimensional array that will later be passed to functions for calculations.
I am having issues with using strtok to extract a column that is not the first as from my understanding, strtok has to read a file sequentially?
i have been using this project to teach myself C, so have had many iterations of this principle to develop my knowledge. I have successfully read csv files, so i understand the basic principles of strtok in csv files.
If i was using the first column to read from, then i can just use strtok as i have been;
var[i][0] = atof(strtok(buf, ","));
var[i][j] = atof(strtok(NULL, ","));
however to read from column 2 onwards, the above code still has to be used as strtok is sequential, but not assign column 0 to the variable. The only rough method i have working is to introduce a temporary variable, place all columns into that, and extract the columns specified by the use, but this is undesirable.
#include<stdio.h>
#include<string.h>
#include<stdint.h>
#include<stdlib.h>
void CSV_Col_read(int r, int c, int start_row, int start_col, float var[r][c])
{
char buf[1024];
float temp[r][c];
FILE *fp = fopen("PV_Data.csv", "r");
if(!fp)
{
printf("Could Not Open File\n");
}
int i = 0;
int index_row = 0;
while(fgets(buf, sizeof buf, fp))
{
index_row++;
if (index_row >= start_row){
if(i >= r - start_row + 1){
break;
}
if (c == 1){
var[i][0] = atof(strtok(buf, ","));
}
else if(start_col >= 2){
temp[i][0] = atof(strtok(buf, ","));
for (int j = 1; j <= c-1; j++)
{
temp[i][j] = atof(strtok(NULL, ","));
}
for (int I = -1; I <= 2; I++){
var[i][I+1] = temp[i][start_col + I];
}
}
else{
var[i][0] = atof(strtok(buf, ","));
for (int j = 1; j <= c-1; j++)
{
var[i][j] = atof(strtok(NULL, ","));
}
}
i++;
}
}
fclose(fp);
}
void printData(int r, int c, int start_row, int start_col, float var[r][c])
{
if ( c == 1){
for (int i = 1; i <= (r - start_row); i++)
{
printf("%f\n", var[i][0]);
}
}
else{
for(int i = 0; i <= (r - start_row); i++)
{
printf("%f", var[i][0]);
for(int j = 1; j <= (c - start_col); j++)
{
printf("\t");
printf("%f", var[i][j]);
}
printf("\n");
}
}
}
int main()
{
int start_row = 705;
int start_col = 3;
int r = 720;
int c = 5;
float var[r][c];
(void) CSV_Col_read(r, c, start_row, start_col, var);
printData(r, c, start_row, start_col, var);
}
the code above is not "insert correct programming word for idiot proof" however as i know i have only specfied the elseif() statement for one scenario. Is this method of a temporary variable the way to go or is there a much cleaner way to approach this? I am not asking for code to fix this and am perfectly happy with an answer that directs me to a learning resource.
Thanks
For something simple where I know the input file will be well-formed and without "empty" values, then I might be doing something like this:
float values[rows][columns] = { 0 }; // Initialize all to zero
char line[512]; // Hopefully large enough
unsigned r; // Row index
// Loop to get all rows, taking care to not go out of bounds
for (r = 0; r < rows && fgets(line, sizeof line, fp) != NULL; ++r)
{
unsigned c = 0; // Column index
// Get the first column value
char *current = strtok(line, ",");
// Loop to get all columns
while (c < columns && current != NULL)
{
values[r][c] = atof(current);
++c; // Increase to next column
current = strtok(NULL, ","); // Get next (if any) column value
}
}
// Here the whole file will have been read and parsed, and the values
// from the file will be in the array `values`.