Buenas, estoy haciendo un programa que dandole una posición y un fichero, escribe lo que pongas en la terminal y lo escribe en la posición introducida.
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#define BUFFER_TAMAINA 512
main(int argc, const char * argv[])
{
int a;
int f,k;
char buff[BUFFER_TAMAINA];
FILE *f1;
if (argc==3)
{
if (strcmp(argv[2],"0")!=0 && atoi(argv[2])==0)
{
write(1, "error, la posicion no es un numero\n", 36);
exit(1);
}
f1=fopen(argv[1], "r+");
if(errno==ENOENT)
{
write(1, "el fichero no existe\n", 28);
exit(1);
}
while(fgetc(f1)!=EOF){k++;}
fclose(f1);
if((atoi(argv[2]))>k)
{
write(1,"la position es demasiado alta\n",28);
exit(1);
}
if(atoi(argv[2])<0){
write(1, "la position es negativa\n", 31);
exit(1);
}
f = open(argv[1], O_WRONLY,00777);
if(errno==ENOENT){
write(1, "el fichero no existe\n", 28);
exit(1);
}
lseek(f, atoi(argv[2]), SEEK_SET);
while ((a=read(0,buff,BUFFER_TAMAINA))>0)
{
write(f,buff,a);
}
close(f);
}
else
{
write(1,"Erabilera: ./idatzi_fitx [fichero] [posicion]\n",50);
}
}
El problema es que en la terminal hay que darle al enter para que lo escriba, es decir esta hecho de manera canónica, y coge tambien el intro como todo lo que queremos escribir. Como podría hacer para que no tuviera en cuenta el enter?
Y como podría hacerlo de forma no canónica? Es decir, que todo lo que vaya escribiendo en la terminal se vaya escribiendo sin necesidad de darle al enter.
Eso depende del terminal, no hay una forma estándar para todo el mundo. Si tienes *nix se hace de una forma, en Windows de otra...
de la forma de unix como seria
Repasa este par de stackoverflow. Lo explica.
https://stackoverflow.com/questions/7469139/what-is-equivalent-to-getch-getche-in-linux
Solo me coge un caracter, le doy a cualquier letra y se acaba el programa guardando la letra en la posición introducida. Como hago para escribir todo lo que quiera?
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <termios.h>
#define BUFFER_TAMAINA 512
void SetTermNoCanon( struct termios *SavedTM)
{
struct termios tm;
tcgetattr(0, &tm);
tcgetattr(0, SavedTM);
tm.c_lflag &= ~(ICANON|ECHO);
tm.c_cc[VMIN]= 1;
tm.c_cc[VTIME]= 0;
tcsetattr(0, TCSANOW, &tm);
}
int main(int argc, const char * argv[])
{
int a;
int f,k;
char buff[BUFFER_TAMAINA];
int p = atoi(buff); //
FILE *f1;
struct stat *stat1;
struct termios saved_tm;
if (argc==3)
{
if (strcmp(argv[2],"0")!=0 && atoi(argv[2])==0)
{
write(1, "error, la posicion no es un numero\n", 36);
exit(1);
}
f1=fopen(argv[1], "r+");
if(errno==ENOENT)
{
write(1, "el fichero no existe\n", 28);
exit(1);
}
while(fgetc(f1)!=EOF){k++;}
fclose(f1);
if((atoi(argv[2]))>k)
{
write(1,"la position es demasiado alta\n",28);
exit(1);
}
if(atoi(argv[2])<0){
write(1, "la position es negativa\n", 31);
exit(1);
}
f = open(argv[1], O_WRONLY,00777);
if(errno==ENOENT){
write(1, "el fichero no existe\n", 28);
exit(1);
}
lseek(f, atoi(argv[2]), SEEK_SET);
SetTermNoCanon( &saved_tm );
while ((a=read(0,buff,BUFFER_TAMAINA))>0)
{
if(stat(argv[1], &*stat1) != NULL)
{
switch(p)
{
case 'q': tcsetattr(0, TCSANOW, &saved_tm);
close(f);
exit(0);
case ' ': break;
default: write(f,buff,a);
printf("Información:\n",argv[1]);
printf("---------------------------\n");
printf("Tamaño: \t \t %d bytes\n", stat1->st_size);
printf("Links: \t%d\n", stat1->st_nlink);
printf("inode: \t \t %d\n", stat1->st_ino);
}
}
}
tcsetattr(0, TCSANOW, &saved_tm);
close(f);
exit(0);
}
else
{
write(1,"Erabilera: ./idatzi_fitx [fichero] [posicion]\n",50);
}
}
No tengo linux para probar el código, pero debería ser una cosa así:
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <termios.h>
// Sacado de https://stackoverflow.com/questions/7469139/what-is-equivalent-to-getch-getche-in-linux
static struct termios old, new;
/* Initialize new terminal i/o settings */
void initTermios(int echo) {
tcgetattr(0, &old); /* grab old terminal i/o settings */
new = old; /* make new settings same as old settings */
new.c_lflag &= ~ICANON; /* disable buffered i/o */
if (echo) {
new.c_lflag |= ECHO; /* set echo mode */
} else {
new.c_lflag &= ~ECHO; /* set no echo mode */
}
tcsetattr(0, TCSANOW, &new); /* use these new terminal i/o settings now */
}
/* Restore old terminal i/o settings */
void resetTermios(void) {
tcsetattr(0, TCSANOW, &old);
}
/* Read 1 character - echo defines echo mode */
char getch_(int echo) {
char ch;
initTermios(echo);
ch = getchar();
resetTermios();
return ch;
}
/* Read 1 character without echo */
char getch(void) {
return getch_(0);
}
/* Read 1 character with echo */
char getche(void) {
return getch_(1);
}
void SetTermNoCanon( struct termios *SavedTM) {
struct termios tm;
tcgetattr(0, &tm);
tcgetattr(0, SavedTM);
tm.c_lflag &= ~(ICANON|ECHO);
tm.c_cc[VMIN]= 1;
tm.c_cc[VTIME]= 0;
tcsetattr(0, TCSANOW, &tm);
}
int main(int argc, const char * argv[]) {
char c;
int f;
long file_end;
long file_pos;
char buff[BUFFER_TAMAINA];
FILE *f1;
struct stat stat1;
// Voy a sustituir todos los write a stdout por printf o puts
// Número de argumentos diferente al esperado
if (argc != 3) {
printf("Uso: %s [fichero] [posicion]", argv[0]);
return EXIT_FAILURE;
}
file_pos = atol(argv[2]);
// No se pueden los metadatos del archivo
if(stat(argv[1], &statl) == -1) {
puts("error, no se pueden recuperar datos del archivo");
return EXIT_FAILURE;
}
// El argumento posición no es un número o es 0
if(file_pos < 1) {
puts("error, posicion debe ser un entero igual o mayor a 1");
return EXIT_FAILURE;
}
f1 = fopen(argv[1], "r+");
// El archivo no existe o no se puede abrir
if(!f1) {
puts("error, el fichero no existe");
return EXIT_FAILURE;
}
//- Sustituyo todo esto
// while(fgetc(f1)!=EOF) {
// k++;
// }
// fclose(f1);
//- Por lo siguiente
fflush(f1);
fseek(f1, 0, SEEK_END);
file_end = ftell(f1);
// La posición entregada está fuera del archivo
if(file_pos>file_end) {
puts("error, la position es demasiado alta");
fclose(f1);
return EXIT_FAILURE;
}
fseek(f1, file_pos, SEEK_SET);
SetTermNoCanon( &saved_tm );
while(c=getche()!=27) {
putc(c, f1);
}
printf("Información: %s\n", argv[1]);
printf("---------------------------\n");
printf("Tamaño: \t \t %d bytes\n", stat1->st_size);
printf("Links: \t%d\n", stat1->st_nlink);
printf("inode: \t \t %d\n", stat1->st_ino);
fclose(f1);
return EXIT_SUCCESS;
}