I'm trying to build a program that prints a "default value" an user can quickly change by deleting parts of it and writing again.
The program would print for example:
enter app name: xcode
The user should be able to replace the "xcode" string (but not the ": " part) and then the program should get the entire input.
Is there a way to do it in plain C with the standard console OSX uses?
Thanks a lot
This will place a prompt and default input on the screen. The arrow keys will move the cursor right and left. Mode may be changed from INS (insert) to OVW
(overwrite) using the Ins key. Enter will terminate input as will too many characters. Valid characters may be restricted by using some combination of LETTERS | NUMBERS | DOT | SPACE | SIGN | PUNCT.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <ctype.h>
#include <sys/select.h>
#include <sys/ioctl.h>
#define ESC 27
#define INSERT 50
#define DELETE 51
#define PGUP 53
#define PGDN 54
#define ARROWRIGHT 67
#define ARROWLEFT 68
#define END 70
#define HOME 72
#define OTHER 79
#define BRACKETLEFT 91
#define TILDE 126
#define BACKSPACE 127
#define LETTERS 1
#define NUMBERS 2
#define DOT 4
#define SPACE 8
#define SIGN 16
#define PUNCT 32
#define SIZE 30
static const int STDIN = 0;
typedef struct Field {
int row;//place input on screen row and col
int col;
int contentsize;//allowed length of input
int inputat;//input at this index
int used;//characters used so far
int valid;//limit input to these characters
int insert;//mode insert/overwrite
int promptrow;//place prompt on screen row and col
int promptcol;
int promptsize;
int lastline;
int lastcol;
int stopon;//stop input with this character
char *content;
char *prompt;
} field;
int kbhit(void)
{
int bytesWaiting;
ioctl(STDIN, FIONREAD, &bytesWaiting);
return bytesWaiting;
}
void prompt ( field *psfield) {
printf ( "\033[%d;%dH", psfield->promptrow, psfield->promptcol);
printf ( "%s", psfield->prompt);
}
int input ( field *psfield) {
int ch = 0;
int to = 0;
printf ( "\033[%d;1H", psfield->lastline);
if ( psfield->insert) {
printf ( "INS");
}
else {
printf ( "OVW");
}
printf ( "\033[%d;%dH", psfield->row, psfield->col);
printf ( "\033[K");//erase to end of line
printf ( "%s", psfield->content);
printf ( "\033[%d;%dH", psfield->row, psfield->col + psfield->inputat);
while ( ( ch = getchar ()) != psfield->stopon) {
printf ( "\033[%d;10H", psfield->lastline);
printf ( "\033[K");//erase to end of line
printf ( "\033[%d;%dH", psfield->row, psfield->col + psfield->inputat);
if (
( ( psfield->valid & LETTERS && isalpha ( ch)))
|| ( ( psfield->valid & SPACE && ch == ' '))
|| ( ( psfield->valid & DOT && ch == '.'))
|| ( ( psfield->valid & SIGN && ( ch == '+' || ch == '-')))
|| ( ( psfield->valid & NUMBERS && isdigit ( ch)))
|| ( ( psfield->valid & PUNCT && ispunct ( ch)))
) {
if ( psfield->insert && psfield->inputat < psfield->used && psfield->used < psfield->contentsize-3) {
//expand
psfield->used++;
for ( to = psfield->used; to >= psfield->inputat; to--) {
psfield->content[to + 1] = psfield->content[to];
}
printf ( "\033[%d;%dH", psfield->row, psfield->col);
printf ( "\033[K");//erase to end of line
printf ( "%s", psfield->content);
}
printf ( "\033[%d;%dH", psfield->row, psfield->col + psfield->inputat);
printf ( "%c", ch);
psfield->content[psfield->inputat] = ch;
psfield->inputat++;
if ( psfield->inputat > psfield->used) {
psfield->used = psfield->inputat;
}
if ( psfield->inputat == psfield->used) {
psfield->content[psfield->inputat] = '\0';
}
if ( psfield->inputat >= psfield->contentsize-1) {
return -1;
}
continue;
}
if ( isprint ( ch)) {
printf ( "\033[%d;10H", psfield->lastline);
printf ( "\033[48;5;124m");//set color white text on red
printf ( "Invalid character");
printf ( "\033[0m");//reset to default colors
printf ( "\033[%d;%dH", psfield->row, psfield->col + psfield->inputat);
continue;
}
if ( ch == BACKSPACE) {
if ( psfield->inputat) {
psfield->inputat--;
//contract
for ( to = psfield->inputat; to <= psfield->used; to++) {
psfield->content[to] = psfield->content[to + 1];
}
psfield->used--;
printf ( "\033[%d;%dH", psfield->row, psfield->col);
printf ( "\033[K");//erase to end of line
printf ( "%s", psfield->content);
printf ( "\033[%d;%dH", psfield->row, psfield->col + psfield->inputat);
}
}
if ( ch == ESC) {
if ( !kbhit ( )) {
continue;
}
ch = getchar ( );
if ( ch == OTHER) {
ch = getchar ( );
if ( ch == HOME) {
psfield->inputat = 0;
printf ( "\033[%d;%dH", psfield->row, psfield->col);
ch = getchar ( );
}
if ( ch == END) {
psfield->inputat = psfield->used;
printf ( "\033[%d;%dH", psfield->row, psfield->col + psfield->inputat);
ch = getchar ( );
}
}
if ( ch == BRACKETLEFT) {
ch = getchar ( );
if ( ch == INSERT) {
ch = getchar ( );
if ( ch == TILDE) {
psfield->insert = !psfield->insert;
printf ( "\033[%d;1H", psfield->lastline);
if ( psfield->insert) {
printf ( "INS");
}
else {
printf ( "OVW");
}
printf ( "\033[%d;%dH", psfield->row, psfield->col + psfield->inputat);
}
}
if ( ch == DELETE) {
ch = getchar ( );
if ( ch == TILDE) {
//contract
for ( to = psfield->inputat; to <= psfield->used; to++) {
psfield->content[to] = psfield->content[to + 1];
}
psfield->used--;
printf ( "\033[%d;%dH", psfield->row, psfield->col);
printf ( "\033[K");//erase to end of line
printf ( "%s", psfield->content);
printf ( "\033[%d;%dH", psfield->row, psfield->col + psfield->inputat);
}
}
if ( ch == ARROWRIGHT) {
if ( psfield->inputat < psfield->used) {
printf ( "\033[C");//cursor right
psfield->inputat++;
}
}
if ( ch == ARROWLEFT) {
if ( psfield->inputat) {
printf ( "\033[D");//cursor left
psfield->inputat--;
}
}
}
else {
ungetc ( ch, stdin);
}
}
}
return 0;
}
int main ( ) {
struct termios oldattr, newattr;
struct winsize w;
field sfield = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '\n', NULL, NULL};
//set terminal
tcgetattr( STDIN, &oldattr );
newattr = oldattr;
newattr.c_lflag &= ~( ICANON | ECHO );
tcsetattr( STDIN, TCSANOW, &newattr );
setbuf(stdin, NULL);
//get terminal dimensions
ioctl( 0, TIOCGWINSZ, &w );
sfield.lastline = w.ws_row;
sfield.lastcol = w.ws_col;
printf ( "\033[2J");//clear screen
sfield.row = 5;
sfield.col = 26;
sfield.promptrow = 5;
sfield.promptcol = 1;
sfield.stopon = '\n';//newline will end input
sfield.valid = LETTERS | SPACE | DOT;
sfield.contentsize = 40;//allowed length of input
if ( ( sfield.content = calloc ( sfield.contentsize, 1)) == NULL) {
printf ( "calloc failed\n");
return 1;
}
sfield.prompt = strdup ( "Enter letters or spaces:");
sfield.promptsize = strlen ( sfield.prompt) + 1;
strcpy ( sfield.content, "default");
sfield.used = strlen ( sfield.content);
prompt ( &sfield);
input ( &sfield);
printf ( "\n\ninput was [%s]\n", sfield.content);
printf ( "\n\nbye\n");
free ( sfield.content);
free ( sfield.prompt);
//restore terminal
tcsetattr( STDIN, TCSANOW, &oldattr );
return 0;
}
Related
SO i was solving this problem and i get this output
**But i am expecting output like this **
what is my mistake here?
I know i don't code efficiently and i want to know how can i make this code more compact any suggestions will be helpful as i am still learning these things.
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
int main()
{
int i,j,k,l,f=0,x=0,q=0,row,column,size;
int res[100];
printf("Enter the row: ");
scanf("%d",&row);
printf("Enter the column: ");
scanf("%d",&column);
size= row*column;
int **arr;
arr=(int**)malloc(row * sizeof(int));
for(i=0;i<row;i++)
{
arr[i] = (int*)malloc(column*sizeof(int));
}
for(i=0;i<row;i++)
{
for (j=0;j<column;j++)
{
printf("Enter the value at row %d and column %d : ",i,j);
scanf("%d",(*(arr+i)+j));
}
}
for(i=0;i<row;i++)
{
for (j=0;j<column;j++)
{
printf("\nThe value at row %d and column %d : %d",i,j,*(*(arr+i)+j));
}
}
printf("\nThe duplicate value(s) are:\n");
for(i=0; i<row; i++)
{
for(j=0; j<column; j++)
{
for(k=0; k<row; k++)
{
for(l=0; l<column; l++)
{
if(*(*(arr+i)+j)== *(*(arr+k)+l))
{
f=f+1;
}
if(f>1)
{
printf("%d in positions (%d,%d)",*(*(arr+i)+j),k,l);
}
}
}f=0;
}
}
free(arr);
}
This is closer to the original code.
skip duplicates that are found closer to the beginning of arr so those are only printed once.
Use a first flag to print the first indices of the first pair of matching values.
pending stores a set of indices to defer printing. This allows printing the last set of indices with a leading and while printing any other indices with a leanding comma.
#include<stdio.h>
#include<stdlib.h>
int scanint ( int *value) {
int result = 0;
result = scanf ( "%d", value);//ampersand not needed. value is int *
if ( 0 == result) {//could not parse an int from input
while ( '\n' != ( result = getchar ( ))) {//read until newline
if ( EOF == result) {
fprintf ( stderr, "EOF\n");
exit ( EXIT_FAILURE);
}
}
return 0;
}
return 1;
}
int main()
{
int eachrow = 0;
int eachcol = 0;
int row = 0;
int column = 0;
int result = 0;
do {
printf ( "Enter the row: ");
fflush ( stdout);
result = scanint ( &row);
} while ( 0 == result);
do {
printf ( "Enter the column: ");
fflush ( stdout);
result = scanint ( &column);
} while ( 0 == result);
int **arr = NULL;
if ( NULL == ( arr = malloc ( sizeof *arr * row))) {
fprintf ( stderr, "malloc arr problem\n");
exit ( EXIT_FAILURE);
}
for ( eachrow = 0; eachrow < row; ++eachrow) {
if ( NULL == ( arr[eachrow] = malloc ( sizeof **arr * column))) {
fprintf ( stderr, "malloc arr[] problem\n");
while ( eachrow) {
eachrow--;
free ( arr[eachrow]);
}
free ( arr);
exit ( EXIT_FAILURE);
}
}
for ( eachrow = 0; eachrow < row; ++eachrow) {
for ( eachcol = 0; eachcol < column; ++eachcol) {
do {
printf ( "Enter the value for (%d %d) : ", eachrow, eachcol);
fflush ( stdout);
result = scanint ( &arr[eachrow][eachcol]);
} while ( 0 == result);
}
}
for ( eachrow = 0; eachrow < row; ++eachrow) {
for ( eachcol = 0; eachcol < column; ++eachcol) {
printf ( "The value at (%d %d) : %d\n", eachrow, eachcol, arr[eachrow][eachcol]);
}
}
char pending[30] = "";
int checkrow = 0;
int checkcol = 0;
int skip = 0;
int first = 0;
int title = 0;
int line = 1;
for ( eachrow = 0; eachrow < row; ++eachrow) {
for ( eachcol = 0; eachcol < column; ++eachcol) {
first = 0;//will need to print the first part of line
pending[0] = 0;//nothing pending
for ( checkrow = 0; checkrow < row; ++checkrow) {
skip = 0;//do not skip
for ( checkcol = 0; checkcol < column; ++checkcol) {
if ( arr[eachrow][eachcol] == arr[checkrow][checkcol]) {//match
if ( checkrow * column + checkcol > eachrow * column + eachcol) {//subsequent match
if ( ! title) {
title = 1;
printf ( "\nThe duplicate value(s) are:\n");
}
if ( ! first) {//need to print first part of line
first = 1;//printed
printf ( "%d. %d in positions (%d,%d)"
, line, arr[eachrow][eachcol], eachrow, eachcol);
}
if ( pending[0]) {//print pending indices
printf ( ", %s", pending);
}
sprintf ( pending, "(%d,%d)", checkrow, checkcol);//copy indices to pending
}
else {//current or previous match
//ignore current match ( checkrow * column + checkcol == eachrow * column + eachcol)
if ( checkrow * column + checkcol < eachrow * column + eachcol) {//previous match
skip = 1;//need to skip checkcol and checkrow
break;//out of for checkcol loop
}
}
}
}
if ( skip) {
break;//out of checkrow loop
}
}
if ( first) {//there were matches
printf ( " and %s\n", pending);//print and with pending indices
}
}
}
if ( ! title) {
printf ( "\nNo duplicates\n");
}
for ( eachrow = 0; eachrow < row; ++eachrow) {
free ( arr[eachrow]);
}
free(arr);
}
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;
}
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++;
}
}
Hi guys I have a question
How do I pass a Multi-dimensional Array from a Function to the main function and from there we want to pass it to another function.
float array2[][3] = get_sizes(numbers);
The compiler says that the string above is an error because getsizes is an invalid initaliser.
Can somebody tell us what we are doing wrong?
Thank you in advance.
EDIT
int main()
{
float anzahl = get_number();
if(feof(stdin))
{
return 0;
}
int anzahl2 = anzahl;
float array2[][3] = get_sizes(anzahl);
if (feof(stdin))
{
return 0;
}
triangulation(array2, anzahl2);
return 0;
}
int get_number(void)
{
printf("Please enter the number of triangles to check: ");
int anzahl = 0;
char check = 0;
int ret = 0;
while(!(ret == 2 && check == '\n'))
{
ret = scanf("%d%c", &anzahl, &check);
if (feof(stdin))
{
return 0;
}
if (check != '\n')
{
printf("[ERR] Invalid number of triangles.\n");
printf("Please enter the number of triangles to check: ");
my_flush();
}
if((check == '\n' && anzahl > UCHAR_MAX) || (check == '\n' && anzahl <= 0))
{
printf("[ERR] Invalid number of triangles.\n");
printf("Please enter the number of triangles to check: ");
ret = 3;
}
}
return anzahl;
void my_flush(void)
{
while(getchar() != '\n')
{
}
}
int vgl(const void *a, const void *b)
{
int aa, bb;
aa = *(int *)a;
bb = *(int *)b;
return (aa - bb);
float get_sizes(int anzahl)
{
float array [3] = {0,0,0};
float array2[100][3];
while(anzahl>0)
{
char check = 0;
int ret = 0;
while(!(ret == 2 && check == '\n'))
{
printf("Please enter the first number of the triplet: ");
ret = scanf("%f%c",&array[0], &check);
if (feof(stdin))
{
return 0;
}
if (check != '\n')
{
printf("[ERR] Invalid number of triangles.\n");
my_flush();
}
if((check == '\n' && array[0] <= 0.0)|| (check == '\n' && array[0] >=
FLT_MAX))
{
printf("[ERR] Invalid number of triangles.\n");
ret = 3;
}
}
check = 0;
ret = 0;
while(!(ret == 2 && check == '\n'))
{
printf("Please enter the second number of the triplet: ");
ret = scanf("%f%c",&array[1], &check);
if (feof(stdin))
{
return 0;
}
if (check != '\n')
{
printf("[ERR] Invalid number of triangles.\n");
my_flush();
}
if((check == '\n' && array[0] <= 0.0)|| (check == '\n' && array[0] >=
FLT_MAX))
{
printf("[ERR] Invalid number of triangles.\n");
ret = 3;
}
}
check = 0;
ret = 0;
while(!(ret == 2 && check == '\n'))
{
printf("Please enter the third number of the triplet: ");
ret = scanf("%f%c",&array[2], &check);
if (feof(stdin))
{
return 0;
}
if (check != '\n')
{
printf("[ERR] Invalid number of triangles.\n");
my_flush();
}
if((check == '\n' && array[0] <= 0.0)|| (check == '\n' && array[0] >=
FLT_MAX))
{
printf("[ERR] Invalid number of triangles.\n");
ret = 3;
}
}
qsort(array, 3, sizeof(array[3]), vgl);
array2[anzahl][0]=array[0];
array2[anzahl][1]=array[1];
array2[anzahl][2]=array[2];
anzahl--;
}
return array2;
float triangulation(float array2[100][3], int anzahl2)
{
int number = 1;
while(anzahl2>0)
{
if(array2[anzahl2][0] == 1 && array2[anzahl2][1] == 1 && array2[anzahl2]
[2] == 2)
{
printf("Tripelt %d (a=%f, b=%f, c=%f)is NO triangle.\n", number,
array2[anzahl2][0], array2[anzahl2][1], array2[anzahl2][2]);
}
else
{
printf("Tripelt %d (a=%f, b=%f, c=%f)is a triangle.\n", number,
array2[anzahl2][0], array2[anzahl2][1], array2[anzahl2][2]);
if(array2[anzahl2][0] == array2[anzahl2][1] && array2[anzahl2][0] ==
array2[anzahl2][2] && array2[anzahl2][1]== array2[anzahl2][2])
{
printf("It is an equilateral triangle.\n");
printf("It is a isosceles triangle.\n");
}
else if(array2[anzahl2][0] == array2[anzahl2][1] || array2[anzahl2][0] ==
array2[anzahl2][2] || array2[anzahl2][1]== array2[anzahl2][2])
{
printf("It is a isosceles triangle.\n");
}
else if(((array2[anzahl2][0])*(array2[anzahl2][0])) + ((array2[anzahl2]
[1])*(array2[anzahl2][1])) == ((array2[anzahl2][2])*(array2[anzahl2][2])))
{
printf("It is a right triangle.\n");
}
}
anzahl2--;
number++;
}
}
This is the whole code i'ts long
and we aren't allowed to use global variables
Here is a demonstrative program that shows how in general it can be done.
#include <stdio.h>
#include <stdlib.h>
#define N 3
float ( * get_sizes( size_t n ) )[N]
{
float ( *a )[N] = malloc( n * sizeof( float[N] ) );
for ( size_t i = 0; i < n; i++ )
{
for ( size_t j = 0; j < N; j++ )
{
a[i][j] = i * N + j;
}
}
return a;
}
void display( float( *a )[N], size_t n )
{
for ( size_t i = 0; i < n; i++ )
{
for ( size_t j = 0; j < N; j++ )
{
printf( "%4.1f ", a[i][j] );
}
putchar( '\n' );
}
}
int main(void)
{
size_t n = 4;
float ( *a )[N] = get_sizes( 4 );
display( a, n );
free( a );
return 0;
}
The program output is
0.0 1.0 2.0
3.0 4.0 5.0
6.0 7.0 8.0
9.0 10.0 11.0
That is you need to allocate the array dynamically.
This simple code indicates you how to send a bi-dimensional array to a function. The function func1 retrieves the value in float a pointed by int x and int y. The same should be done also for more than two dimensions.
#include <stdio.h>
float func1(float *,int x, int y,int mx, int my);
float func1(float * a,int x, int y,int mx, int my)
{
if (x>=mx)
return 0;
if (y>=my)
return 0;
return a[x*my+y];
}
int main(void)
{
#define _MX 4
#define _MY 3
int x, y;
float a[_MY][_MX] = {
{0.0,0.1,0.2,0.3},
{1.0,1.1,1.2,1.3},
{2.0,2.1,2.2,2.3}
};
for(x=0;x<_MX;x++) {
for(y=0;y<_MY;y++){
// With cast
printf("x =%2d y =%2d => v = %f\n",x,y,func1((float *)a,x,y,_MX,_MY));
}
}
puts("---------------------------------");
for(x=0;x<_MX;x++) {
for(y=0;y<_MY;y++){
// Without cast
printf("x =%2d y =%2d => v = %f\n",x,y,func1(a[0],x,y,_MX,_MY));
}
}
return 0;
}
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", ¢er)) != 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;
}