Insert an element in a specified position in a given array - c

How can I insert a value in specific position in C?
For example:
const char filenameC[] ="AndModel.c";
FILE * fileC=fopen(filenameC,"r");
int LineNumber=1;
char line[200],search_string[]="similar";
if( fileC)
{
while ( fgets ( line, 200, fileC ) != NULL )
{
if(strstr(line,search_string))
{
fputs ( line, stdout );
printf("%d", LineNumber);
}
LineNumber++;
}
}
FILE * fileW=fopen(filenameC,"w");
fseek(fileW, LineNumber,SEEK_SET);
fputs("hello",fileW);
printf("\n");
return 0;

Alright here's your solution:
for (int i = number_of_elements -1; i >= desired_position; i--)
{
line[i + 1] = line[i];
}
line[desired_position] = value;
So in the case of your code, if I wanted to insert an element of the array to position 3, and set that value to 'd', then I would just do it like this:
if (fileC)
{
while (fgets (line, 200, fileC) != NULL)
{
if (strstr (line, search_string))
{
for (int i = 200 - 1; i >= 3; i--)
{
line[i+1] = line[i];
}
line[3] = 'd';
printf ("%s", line);
fputs (line, stdout);
printf ("%d", LineNumber);
}
LineNumber++;
}
}

Related

output is different when I use default value vs user input

I am doing some pattern searching in a string for my homework. When I was testing the code, I declared a default value for easy testing. When I am done with the testing and tried to run the code using user input, the output is different.
The output (when used default value) "Match at position 4." but when use user input, it says "no match".
This is my code:
int main() {
char text[255], pattern[255];
char sensitive = 'N';
int n, a[255], i, j, k = 0, l, found = 0, t = 0, temp=0;
printf("Enter a sentence , up to 255 characters:");
fgets(text, 255, stdin);
text[strcspn(text, "\n")] = 0;
printf("Enter a pattern , up to 255 characters:");
fgets(pattern, 255, stdin);
pattern[strcspn(pattern, "\n")] = 0;
printf("Should the match be case-sensitive, Y or N?");
scanf("%c", &sensitive);
if (sensitive == 'N' || sensitive == 'n') {
for (i = 0; i < strlen(text); i++) {
text[i] = tolower(text[i]);
//printf("%c", text[i]);
}
for (i = 0; i < strlen(pattern); i++) {
pattern[i] = tolower(pattern[i]);
//printf("%c", pattern[i]);
}
}
for (i = 0;text[i] != '\0';i++)
{
j = 0;
if (text[i] == pattern[j] || pattern[j] == '.')
{
temp = i + 1;
while (text[i] == pattern[j] || pattern[j] == '.')
{
i++;
j++;
}
if (pattern[j] == '\0')
{
temp -= 1;
printf("Matches at position %d\n", temp);
exit(0);
}
else
{
i = temp;
temp = 0;
}
}
}
if (temp == 0)
printf("No match.\n");
return 0;
}
This tests if text or pattern are at the terminating zero so the index does not go beyond the array boundary.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int main ( void) {
char text[255], pattern[255];
char sensitive[3] = "N";
int i, j, temp=0;
printf ( "Enter a sentence , up to 255 characters:");
if ( ! fgets(text, 255, stdin)) {
fprintf ( stderr, "fgets problem [text]\n");
return 0;
}
text[strcspn(text, "\n")] = 0;
printf ( "Enter a pattern , up to 255 characters:");
if ( ! fgets(pattern, 255, stdin)) {
fprintf ( stderr, "fgets problem [pattern]\n");
return 0;
}
pattern[strcspn(pattern, "\n")] = 0;//remove newline
printf ( "Should the match be case-sensitive, Y or N?");
if ( ! fgets( sensitive, sizeof sensitive, stdin)) {
fprintf ( stderr, "fgets problem [sensitive]\n");
return 0;
}
if ( sensitive[0] == 'N' || sensitive[0] == 'n') {
for ( i = 0; text[i]; i++) {
text[i] = tolower(text[i]);
}
for (i = 0; pattern[i]; i++) {
pattern[i] = tolower(pattern[i]);
}
}
for ( i = 0; text[i] != '\0';i++) {
j = 0;
temp = i + 1;
while ( pattern[j] && text[i + j]
&& ( text[i + j] == pattern[j] || pattern[j] == '.')) {
j++;
}
if (pattern[j] == '\0') {
temp -= 1;
printf("Matches at position %d\n", temp);
exit(0);
}
else {
temp = 0;
}
}
if (temp == 0) {
printf("No match.\n");
}
return 0;
}

Why am I getting this message in hackerrank "~ no response on stdout ~"? I don't know what I am missing>

Why am I getting this message in hackerrank "~ no response on stdout ~"? I don't know what I am missing?
I am bit frustrated right now because I have no clue about what to do.
So I was left with only choice to post this query on Stackoverflow.
Here is the link to the problem
Here is my complete code:
char* readline();
// Complete the countingValleys function below.
int countingValleys(int n, char* s)
{
int dwnhl = 0, level = 0;
bool frmsurface = true;
int k = strlen(s);
for (int i = 0; i < k; i++)
{
if (level == 0)
{
frmsurface = true;
}
if (s[i] == 'D')
{
level--;
if ((level < 0) && (frmsurface == true))
{
dwnhl++;
frmsurface = false;
//printf("went downhill %d ",i);
}
}
else if (s[i] == 'U')
{ //printf("went uphill %d ",i);
level++;
}
// printf("\nhello - %c",s[i]);
}
printf("\nNumber of downhill = %d \n", dwnhl);
return (dwnhl);
}
int main()
{
FILE* fptr = fopen(getenv("OUTPUT_PATH"), "w");
char* n_endptr;
char* n_str = readline();
int n = strtol(n_str, &n_endptr, 10);
if (n_endptr == n_str || *n_endptr != '\0')
{
exit(EXIT_FAILURE);
}
char* s = readline();
int result = countingValleys(n, s);
printf("%d\n", result);
return 0;
}
char* readline()
{
size_t alloc_length = 1024;
size_t data_length = 0;
char* data = malloc(alloc_length);
while (true)
{
char* cursor = data + data_length;
char* line = fgets(cursor, alloc_length - data_length, stdin);
if (!line)
{
break;
}
data_length += strlen(cursor);
if (data_length < alloc_length - 1 || data[data_length - 1] == '\n')
{
break;
}
size_t new_length = alloc_length << 1;
data = realloc(data, new_length);
if (!data)
{
break;
}
alloc_length = new_length;
}
if (data[data_length - 1] == '\n')
{
data[data_length - 1] = '\0';
}
data = realloc(data, data_length);
return data;
}
One problem is the way you handle frmsurface
The first time you enter the loop frmsurface is set to true. If the events are UUDD, your code will still count a "valley" because you don't clear frmsurface when you go up.
Instead of
if(level==0)
{
frmsurface=true;
}
you could try:
frmsurface = (level == 0);
but I don't really understand why you want the boolean. Just test for level == 0 instead. Something like:
if(s[i]=='D')
{
if(level==0)
{
dwnhl++;
}
level--;
}
else if (s[i]=='U')
{
level++;
}
Also I wonder if this line:
printf("\nNumber of downhill = %d \n", dwnhl);
must be removed.
Notice that
int k=strlen(s);
for(int i=0;i<k;i++)
could probably just be
for(int i=0;i<n;i++)
^
as n is passed to the function

Parse comma serpataed file of different types

This is what I came up with for reading a csv file with multiple types. It seems to get the job done in all cases but 1,2,,"a". Where there is a blank space. Can I please have some ideas on how to fix this?
const char* getfield(char* line, int num)
{
const char* tok;
for (tok = strtok(line, ",");
tok && *tok;
tok = strtok(NULL, ",\n"))
{
if (!--num)
return tok;
}
return NULL;
}
while(fgets(line, 80, inputfp1) != NULL)
{
printf(" line is %s \n", line);
char* tmp1 = strdup(line);
char* tmp2 = strdup(line);
char* tmp3 = strdup(line);
char* tmp4 = strdup(line);
printf("Field 1 would be %s\n", getfield(tmp1, 1));
printf("Field 2 would be %s\n", getfield(tmp2, 2));
printf("Field 3 would be %s\n", getfield(tmp3, 3));
printf("Field 4 would be %s\n", getfield(tmp4, 4));
// NOTE strtok clobbers tmp
free(tmp1);
free(tmp2);
free(tmp3);
free(tmp4);
//sscanf(line, "%d, %d, %d, %d", &column1[i], &column2[i], &column3[i], &column4[i]);
//printf(" column1[i] is %d column2[i] is %d column3[i] is %d column4[i] is %d \n", column1[i], column2[i], column3[i], column4[i]);
i++;
memset(line, 0, 80);
}
Ok I used a library like was suggested and don't understand why this is not working.
https://ideone.com/RylYp1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
* Given a string which might contain unescaped newlines, split it up into
* lines which do not contain unescaped newlines, returned as a
* NULL-terminated array of malloc'd strings.
*/
char **split_on_unescaped_newlines(const char *txt) {
const char *ptr, *lineStart;
char **buf, **bptr;
int fQuote, nLines;
/* First pass: count how many lines we will need */
for ( nLines = 1, ptr = txt, fQuote = 0; *ptr; ptr++ ) {
if ( fQuote ) {
if ( *ptr == '\"' ) {
if ( ptr[1] == '\"' ) {
ptr++;
continue;
}
fQuote = 0;
}
} else if ( *ptr == '\"' ) {
fQuote = 1;
} else if ( *ptr == '\n' ) {
nLines++;
}
}
buf = malloc( sizeof(char*) * (nLines+1) );
if ( !buf ) {
return NULL;
}
/* Second pass: populate results */
lineStart = txt;
for ( bptr = buf, ptr = txt, fQuote = 0; ; ptr++ ) {
if ( fQuote ) {
if ( *ptr == '\"' ) {
if ( ptr[1] == '\"' ) {
ptr++;
continue;
}
fQuote = 0;
continue;
} else if ( *ptr ) {
continue;
}
}
if ( *ptr == '\"' ) {
fQuote = 1;
} else if ( *ptr == '\n' || !*ptr ) {
size_t len = ptr - lineStart;
if ( len == 0 ) {
*bptr = NULL;
return buf;
}
*bptr = malloc( len + 1 );
if ( !*bptr ) {
for ( bptr--; bptr >= buf; bptr-- ) {
free( *bptr );
}
free( buf );
return NULL;
}
memcpy( *bptr, lineStart, len );
(*bptr)[len] = '\0';
if ( *ptr ) {
lineStart = ptr + 1;
bptr++;
} else {
bptr[1] = NULL;
return buf;
}
}
}
}
int main(void) {
// your code goes here
char line[80] = "52,243,,542";
split_on_unescaped_newlines(line);
printf("line %s\n", line[0]);
printf("line %s\n", line[1]);
return 0;
}

Assigning data to 2D array and displaying it C

I am writing a program, that will open csv file and save data to 3D array.
Most of code works pretty good, but I have a problem with assiging records to 2D array.
Here is a code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define FILE_MODE "r"
/*
Explode string with given token and assign result to list variable
*/
int explode(const char *src, const char *tokens, char ***list, size_t *len)
{
if(src == NULL || list == NULL || len == NULL) {
return 0;
}
char *str, *copy, **_list = NULL, **tmp;
*list = NULL;
*len = 0;
copy = strdup(src);
if(copy == NULL)
return 1;
str = strtok(copy, tokens);
if(str == NULL) {
goto free_and_exit;
}
_list = realloc(NULL, sizeof *_list);
if(_list == NULL) {
goto free_and_exit;
}
_list[*len] = strdup(str);
if(_list[*len] == NULL)
goto free_and_exit;
(*len)++;
while((str = strtok(NULL, tokens)))
{
tmp = realloc(_list, (sizeof *_list) * (*len + 1));
if(tmp == NULL)
goto free_and_exit;
_list = tmp;
_list[*len] = strdup(str);
if(_list[*len] == NULL)
goto free_and_exit;
(*len)++;
}
free_and_exit:
*list = _list;
free(copy);
return 2;
}
/*
Exploding lines in CSV file
*/
const char* getfield(char* line, int num)
{
const char* tok;
for (tok = strtok(line, ";");
tok && *tok;
tok = strtok(NULL, ";\n"))
{
if (!--num)
return tok;
}
return NULL;
}
int main()
{
FILE *stream;
char fileName[256], table[256], line[256],
**list, **columns, **data;
size_t length;
printf("Witaj uzytkowniku! Podaj nazwe pliku z rozszerzeniem .csv. \n");
scanf("%s", fileName);
explode(fileName, ".", &list, &length);
strcpy(table, list[0]);
stream = fopen("file.csv", FILE_MODE); // not to write path every single time
if (stream == NULL) {
printf("Nie moge otworzyc pliku %s do odczytu!\n", fileName);
exit(1);
}
fgets(line, sizeof line, stream);
explode(line, ";", &columns, &length);
int recordNumber = 0
,columnNumber = 0;
while (fgets(line, sizeof line, stream))
{
char* tmp = strdup(line);
if (getfield(tmp, recordNumber) != NULL) {
columnNumber++;
}
recordNumber++;
free(tmp);
}
fseek(stream, 0, SEEK_SET); // Go to beginning of file
fgets(line, 1024, stream);
int i = 0 // Number of records
,h = 0; // number of columns
char **records[recordNumber][columnNumber];
length = 0;
char *tmp[recordNumber];
// Here I get number of lines and columns in csv file to make 3D array??
while (fgets(line, sizeof line, stream) && i < recordNumber)
{
tmp[i] = strdup(line);
explode(tmp[i], ";", &data, &length);
for (h = 0; h < columnNumber; h++)
{
memcpy(records[i][h], data[h], sizeof(data[h]));
}
i++;
}
for (i = 0; i < recordNumber; i++)
{
for (h = 0; h < columnNumber; h++)
{
printf("%s ", records[i][h][0]);
}
printf("\n");
}
fclose(stream);
return EXIT_SUCCESS;
}
Problem starts, when I try do a loop, that assign data to array:
while (fgets(line, sizeof line, stream) && i < recordNumber)
{
tmp[i] = strdup(line);
explode(tmp[i], ";", &data, &length);
for (h = 0; h < columnNumber; h++)
{
memcpy(records[i][h], data[h], sizeof(data[h]));
}
i++;
}
I tried to use memcpy and strcpy, but none works correctly - I am pretty sure.
When code goes to these lines, there is an error: segmentation fault (core dumping).
All i want to achieve is to fill this array with data from csv file and print it.
Thanks for your help! :)
EDIT:
explode function is not mine. Probably, I found it somewhere on stackoverflow.
When, it comes to the code, after little change, it works
char records[recordNumber][columnNumber][1024];
length = 0;
char *tmp[recordNumber];
while (fgets(line, sizeof line, stream) && i < recordNumber)
{
tmp[i] = strdup(line);
explode(tmp[i], ";", &data, &length);
for (h = 0; h < columnNumber; h++)
{
strcpy(records[i][h], data[h]);
}
i++;
}
Read each line of the file with fgets. strpbrk can be used to find the delimiters. Two pointers can be used to get the number of characters between the delimiters. Then allocate memory and use memcpy to copy the field to the allocated memory.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char ***strpdlm ( char *pdelim, int skip);
char ***freedlm ( char ***ppp);
int main()
{
char ***expld = NULL;
int line = 0;
int field = 0;
//last argument of 1 is skip consecutive delimiters. 0 do not skip
expld = strpdlm ( ";\n", 1);// delimiters semicolon and newline
//print each extracted string
line = 0;
if ( expld) {//not null
while ( expld[line]) {//not null
field = 0;
printf ( "\nfields for line %d\n", line);
while ( expld[line][field]) {//not null
printf ( "expld[%d][%d] %s\n", line, field, expld[line][field]);
field++;
}
line++;
}
}
//free memory and set NULL
expld = freedlm ( expld);
return 0;
}
char ***freedlm ( char ***ppp) {
size_t each = 0;
size_t item = 0;
if ( ppp) {
while ( ppp[each]) {
item = 0;
while ( ppp[each][item]) {
free ( ppp[each][item]);
item++;
}
free ( ppp[each]);
each++;
}
free ( ppp);
}
return NULL;
}
char ***strpdlm ( char *pdelim, int skip) {
char ***xpld = NULL;
char ***temprecord = NULL;
char **tempfield = NULL;
char *pnt = NULL;
char *cur = NULL;
char line[1024] = "";
int span = 0;
int len = 0;
int record = 0;
int field = 0;
FILE *pf = NULL;
if ( ( pf = fopen ( "file.csv", "r")) == NULL) {
perror ( "could not open \"file.csv\"");
return NULL;
}
if ( pdelim) {
while ( fgets ( line, sizeof line, pf)) {
//make sure each line ends with \n
len = strcspn ( line, "\n");
if ( len + 1 < sizeof line) {
line[len] = '\n';
line[len + 1] = '\0';
}
//allocate record + 2 pointers
if ( ( temprecord = realloc ( xpld, ( record + 2) * sizeof ( *xpld))) == NULL) {
fprintf ( stderr, "problem realloc records\n");
fclose ( pf);
return xpld;
}
xpld = temprecord;
xpld[record] = NULL;
field = 0;
cur = line;//cur points to line
while ( ( pnt = strpbrk ( cur, pdelim))) {
if ( pnt != cur || !skip) {
if ( ( tempfield = realloc ( xpld[record], ( field + 2) * sizeof ( **xpld))) == NULL) {
fprintf ( stderr, "problem realloc fields\n");
fclose ( pf);
return xpld;
}
xpld[record] = tempfield;
xpld[record][field] = NULL;
if ( pnt) {
span = pnt - cur;
}
else {
span = strlen ( cur);
}
if ( ( xpld[record][field] = malloc ( span + 1)) == NULL) {
fprintf ( stderr, "problem malloc\n");
fclose ( pf);
return xpld;
}
memcpy ( xpld[record][field], cur, span);
xpld[record][field][span] = '\0';
field++;
xpld[record][field] = NULL;//sentinel NULL
}
cur = pnt + 1;//set cur to point to next field
}
record++;
xpld[record] = NULL;//sentinel NULL
}
}
fclose ( pf);
return xpld;
}

How to implement `.nf` formatting feature

I have written a program that reads a text file inputted by the user, and inside the file contains formatting features such as .br , .sp and .nf.
.nf symbolises no fill, also meaning that when you see any formatting feature after .nf they should all be ignored and it should just output the text in the format it originally appears in the text file.
For example:
.nf Hello my name is .br Jay.
Output:
Hello my name is Jay
If .nf was not there the output would be:
Hello my name is
Jay.
Here's my code:
int main(void) {
FILE *fp = NULL;
char file_name[257] = {'\0'};
char line[61] = {'\0'};
char word[61] = {'\0'};
int out = 0;
int blanks;
int space;
int useFormats = 1;
printf ( "Enter file name:\n");
scanf ( " %256[^\n]", file_name);
if ( ( fp = fopen ( file_name, "r")) == NULL) {
printf ( "could not open file\n");
return 1;
}
while (useFormats == 1){
while ( ( fscanf ( fp, "%60s", word)) == 1) { //breaks the sentence after .br
if ( strcmp ( word, ".br") == 0) {
printf ( "%s\n", line);
line[0] = '\0';
out = 1;
}
if ( strcmp ( word, ".nf") == 0) {// stop filling lines (no fill)
useFormats == 0;
line[0] = '\0';
out = 1;
}
if ( strncmp ( word, ".sp", 3) == 0) { // creates n amount of spaces after .sp
if ( ( sscanf ( &word[3], "%d", &blanks)) == 1) {
printf ( "%s\n", line);
while ( blanks) {
blanks--;
printf ( "\n");
}
line[0] = '\0';
out = 1;
}
else {
printf ( "%s\n", line);
line[0] = '\0';
out = 1;
}
}
else if ( strlen ( line) + strlen ( word) + 1 < 60) {
strcat ( line, " ");
strcat ( line, word);
out = 0;
}
else {
printf ( "%s\n", line);
strcpy ( line, word);
out = 1;
}
}
if ( !out) {
printf ( "%s\n", line);
}
fclose ( fp);
return 0;
}
}
I tried creating a variable called useFormats which is true whilst running and I make it false when it reaches to the .nf feature but nothing happens. I'm not sure if I should remove the if statement and create another while loop to say while (useFormats == 0) to implement the .nf feature.
This should capture the ".nf" token and set useFormats to zero. Adding if ( useFormats == 1) { to the other format conditions should disable them.
#include <stdio.h>
#include <string.h>
#define WIDTH 80
int main(void) {
FILE *fp = NULL;
char file_name[257] = {'\0'};
char line[61] = {'\0'};
char word[61] = {'\0'};
int out = 0;
int blanks = 0;
int center = 0;
int useFormats = 1;
int margin = 0;
printf ( "Enter file name:\n");
scanf ( " %256[^\n]", file_name);
if ( ( fp = fopen ( file_name, "r")) == NULL) {
printf ( "could not open file\n");
return 1;
}
while ( ( fscanf ( fp, "%60s", word)) == 1) {// read file to end one word at a time
if ( strcmp ( word, ".nf") == 0) {// no formatting)
useFormats = 0;
center = 0;
continue;
}
if ( strncmp ( word, ".ce", 3) == 0) {
if ( useFormats == 1) {
if ( ( sscanf ( &word[3], "%d", &center)) != 1) {
center = 0;
}
}
continue;
}
if ( strncmp ( word, ".sp", 3) == 0) {
if ( useFormats == 1) {
if ( ( sscanf ( &word[3], "%d", &blanks)) == 1) {
margin = 0;
if ( center) {
margin = WIDTH - ( ( WIDTH - strlen ( line)) / 2);
center--;
}
printf ( "%*s\n", margin, line);
while ( blanks) {
blanks--;
printf ( "\n");
}
line[0] = '\0';
out = 1;
}
else {
margin = 0;
if ( center) {
margin = WIDTH - ( ( WIDTH - strlen ( line)) / 2);
center--;
}
printf ( "%*s\n", margin, line);
line[0] = '\0';
out = 1;
}
}
continue;
}
if ( strcmp ( word, ".br") == 0) {
if ( useFormats == 1) {
margin = 0;
if ( center) {
margin = WIDTH - ( ( WIDTH - strlen ( line)) / 2);
center--;
}
printf ( "%*s\n", margin, line);
line[0] = '\0';
out = 1;
}
continue;
}
if ( strlen ( line) + strlen ( word) + 1 <= 60) {
strcat ( line, " ");
strcat ( line, word);
out = 0;
}
else {
margin = 0;
if ( center) {
margin = WIDTH - ( ( WIDTH - strlen ( line)) / 2);
center--;
}
printf ( "%*s\n", margin, line);
strcpy ( line, word);
out = 1;
}
}
if ( !out) {
margin = 0;
if ( center) {
margin = ( WIDTH - strlen ( line)) / 2;
center--;
}
printf ( "%*s\n", margin, line);
}
fclose ( fp);
return 0;
}
As long as this: while ( ( fscanf ( fp, "%60s", word)) == 1) evaluates as true it will never break from the while current inner while loop. You can break out of the inner while loop with break; after your condition is met. It will then check the condition and break out of the main while loop. You also don't assign a value with ==. That operand is for evaluation.
if ( strcmp ( word, ".nf") == 0) {// stop filling lines (no fill)
useFormats = 0;
line[0] = '\0';
out = 1;
break;
}

Resources