c语言中多样的循环控制语句

循环语句是c语言重要的基础语法之一

常见的循环控制语句for, while, do-while
因为do-while与while区别仅在于是否至少执行一次的代码有区别,故对前者不作讨论

c/c++的真值变量

  • 在c/c++中,作为真值的变量为数字,判断条件自认为比较方便。
    非0为真,0为假,控制循环语句的执行与否
if (1) printf("1\n");
if (2) printf("2\n");
if (0) printf("0\n");

可以看到0没有输出
还可以放赋值语句:

if (n = 3) printf("3\n");

输出值3。

简单过一下基础

for循环基础结构

for (初始化表达式; 条件表达式; 更新表达式) {
// 循环体
}

最常用的形式

for (int i = 0; i < n; i++) {
        printf("Hello, world!\n");
    }

while循环基础结构

while (条件表达式) {
// 循环体
}

  • 条件表达式:判断是否执行下一次循环,若是,则执行循环体内代码,反之退出循环

最常用的形式

while (n需要满足的条件) {
        if (条件) {
            n自增或自减
        }
    }

循环控制语句

  • break语句
    跳出最内层的循环,针对所在的内层循环

  • continue语句
    跳过此次循环未执行部分,重新开启下一次循环,针对所在的内层循环

  • 其它语句loop-goto
    用于转到标记的语句

循环语句的变体,灵活地选择合适的循环结构

结合break, continue, goto,return(特别是while循环)可以使程序更加灵活

变量标记法(文章中记为flag)

使语句可以执行有限次
比如一次:

int flag = 1;
int n = 5;
while (n--) {
	if (flag) {
		flag = 0;
		printf("if内\n");
	}
	printf("if外\n");
}

输出:
输出

改变程序下一步执行方向

int flag = 1;

for (; 1/*具体条件*/;) {
	while (1/*具体条件*/) {
		while (1/*具体条件*/) {
			if (flag) {
				// 示例执行代码
				printf("hello\n");
			} else {
				// 示例执行代码
				printf("world\n");
			}
		}
	}
}

结束特定循环

int flag = 1;

for (; 1/*具体条件*/;) {
	while (flag) {
		while (1/*具体条件*/) {
			if (1/*具体条件*/) {
				// 示例执行代码
				flag = 0;
				printf("hello\n");
			} else {
				// 示例执行代码
				printf("world\n");
			}
		}
	}
}

// 或者:

int flag = 1;

for (; flag;) {
	while (1/*具体条件*/) {
		while (1/*具体条件*/) {
			if (1/*具体条件*/) {
				// 示例执行代码
				flag = 0;
				printf("hello\n");
			} else {
				// 示例执行代码
				printf("world\n");
			}
		}
	}
}

特别是在获取正确用户输入时非常有用:

int mineClear(char innerBoard[LENGTH][LENGTH], char outerBoard[LENGTH][LENGTH]) {
	int x = 0, y = 0;
	int flag = 1;   <-----------------标记变量
	int status = 0;
	while (flag) {   <-----------------标记变量控制的循环
		printf("PLease input your coordinate: \n");
		scanf("%d %d", &x, &y);
		x--;
		y--;
		if (!(x >= 0 && x < LENGTH && y >= 0 && y < LENGTH)) {
			printf("Illegal input.Please input again.\n");
		} else {
			if (outerBoard[x][y] != ' ') {
				printf("Explored!!");
				continue;
			} else {
				if (innerBoard[x][y] == '*') {
					system("cls");
					showBoard(innerBoard);
					Sleep(1000);
					printf("==================================================\n");
					printf("You died!!!\n");
					++status;
				} else {
					extendSize(innerBoard, outerBoard, x, y);
					if (residue == 0) {
						system("cls");
						showBoard(innerBoard);
						Sleep(1000);
						printf("==================================================\n");
						printf("You win!!!\n");
						status = 2;
					}
				}
			}
			flag = 0;        <-----------------用户正确输入置为0,结束循环
		}
	}
	return status;
}

for循环进阶用法

  • 空的初始化语句
int i = 0;
    
    // 中间对i进行处理,i的值会变得未知,示例:
    i = 3; // 比如重新设置i的值
    int x = 2;
    while(--x) { // 比如在循环中操作它
        i++;
    } 
    
    for (;i < 10; i++) {
        // 执行循环体
        printf("%d\n", i);
    }
  • 空的条件语句
int i = 10;
    while(1) {
        // todo something (内含跳出语句break,goto或return)
        i--;
    }

比如以上代码可重写为:

for (int i = 10;;i--) {
    // todo something (内含跳出语句break,goto或return)
}
  • 空的迭代语句
    可以选择性迭代i的值
for (int i = 0; i < 10;) {
        // 满足某条件,如:
        int sum = 0;
        sum++;
        if (sum % 2) {
            // 迭代i的值
            i++;
        }
    }

比如接收正确的数据(如用户输入)才能迭代:

	int x = 0;
    for (int i = 0; i < 10;) {
        scanf("%d", &x);
        // x满足某条件,如:
        if (x > 0) {
        	// 迭代i的值
            i++;
        }
    }

只要你想,你可以用for替代while:

for (; n--;) {
	// todo something
	printf("%d\n", n);
}
while (n--) {
	// todo something
	printf("%d\n", n);
}

(油饼)

  • 双变量操作
    比如实现数组逆序:
void reserve(int *arr, int len) {
	// 同时对两个变量操作,提升性能
	for (int i = 0, j = len - 1; i < j; ++i, --j) {
		int temp = arr[i];
		arr[i] = arr[j];
		arr[j] = temp;
	}
}

void print(int* arr, int len) {
	printf("[");
	for (int i = 0; i < len; ++i) {
		printf(i == len - 1 ? "%d]" : "%d, ", arr[i]);
	}
}

int main() {
	int arr[10] = { 
		1, 2, 3, 4, 5, 6, 7, 8, 9, 0
	};
	// 逆序数组
	int len = sizeof(arr) / sizeof(int);
	reserve(arr, len);
	print(arr, len);
}

逆序后数组

loop-goto与循环的结合

通过合理放置loop,结合也可实现类似循环的效果
看下列代码

int flag = 10;
    loop :
    printf("Hello, world!\n");
    if (flag) {
        flag--;
        goto loop;
    }

基于loop-goto的循环
这与

for (int i = 0; i < 10; i++) {
        printf("Hello, world!\n");
    }

的输出结果一样。

从深层次的循环中退出到指定位置,比continue,break更加灵活
看下列代码:

loop1 :
while (1/*具体条件*/) {
	loop2 :
	while (1/*具体条件*/) {
		// 其它代码
		while (1/*具体条件*/) {
			// 其它代码
			if (1/*具体条件*/) {
				// 其它代码
				goto loop1;
			} else if (2/*具体条件*/) {
				// 其它代码
				goto loop2;
			} else if (3/*具体条件*/) {
				// 其它代码
				goto loop3;
			}
			// 其它代码
		}
	}
	// 其它代码
loop3 :
	// 其它代码
}

灵活性给足了,但也因为灵活度太高,容易出bug。其超高的灵活性,通常被认为是降低代码可读性的语句,不推荐大量使用,但是见到了也要知道,说不定什么地方可以起到出奇不意的效果。

在一些面向对象语言中,也有实现类似循环的效果

对象在创建时会初始化,这时如果有一个静态的成员变量,可以在每次创建一个对象时,更改变量的值,那么一次性创建多个对象就可以实现一个变量的不断增加。
怎样方便的一次性创建多个对象呢,创建一个该对象的数组就可以实现。
比如在c++中:

class A {
    static int a;

public:
    A() {
        a++;
    }

    [[nodiscard]] static int getA() {
        return a;
    }
};
int A::a = 0;
int main() {
    A* test = new A[10];
    std::cout << A::getA() << std::endl;
}

输出a的值为
a的值
在Java中:

package day_05_;

public class A {
    private static int a = 0;
    public A() {
        a++;
    }

    public int getA() {
        return a;
    }
}

class B {
    public static void main(String[] args) {
        A[] arr = new A[5];
        // 显式初始化对象A数组
        for (int i = 0; i < arr.length; i++) {
            arr[i] = new A();
        }
        System.out.println(arr[0].getA());
    }
}

a的值
注意:
Java:创建对象数组时,数组中的元素默认为 null,需要显式初始化。
C++:创建对象数组时,数组中的每个元素都会被自动初始化。

你是说我创建一个对象数组就为了改变一个值?
当然不仅仅是变量,各种数据结合某一特定业务场景这种有实际需求的时候,才可能认为它有用,在创建对象时当然也可以处理多组数据,这不妨是一个新的思路。

综合应用

虽然是Java代码,但在循环方面除了真值变量与c区别不大,而且c是其它语言的基础,所以主要理解循环控制就行

public static boolean logIn(ArrayList<User> usersList) {
        if (usersList.isEmpty()) {
            System.out.println("No user found. Please register first.");
            return false;
        }
        System.out.println("Logging in");
        Scanner sc = new Scanner(System.in);
        System.out.print("Enter your username: ");
        String username = sc.nextLine();
        System.out.println("Enter 1 to continue, 2 to find password, 0 to exit");
        for (int i = 0; i < 1; ) {          <---------------空迭代语句
            int input = sc.nextInt();
            sc.nextLine();
            if (input == 1) {
                i++;                               <------------只有用户名正确才会进行迭代
                System.out.println("Enter your password: ");
                String password = sc.nextLine();
                for (int j = 0; j < usersList.size(); j++) {
                    if (usersList.get(j).login(username, password)) {
                        System.out.println("Logged in successfully.");
                        return true;
                    }
                    System.out.println("Invalid username or password.");
                }
            } else if (input == 2) {
                findPassword(usersList);
                return false;
            } else if (input == 0) {
                System.out.println("Exiting.");
                return false;
            } else {
                System.out.println("Invalid input. Please try again.");
            }
        }
        return false;
    }
public static void addStuInfo(ArrayList<Student> list) {
        Student stu = new Student();
        Scanner sc = new Scanner(System.in);
        boolean flag = true;

        loop:                       <-----------------从深层循环中跳出
        while (flag) {               <================正确输入结束当前输入才能结束
            System.out.print("Enter id: ");
            stu.setId(sc.next());
            for (int i = 0; i < list.size(); i++) {
                if (list.get(i).getId().equals(stu.getId())) {
                    System.out.println("id already exists.");
                    System.out.println("Please enter another id.");
                    continue loop;                        <------------------java形式的跳转语句,等价与c的goto
                }
            }

            System.out.print("Enter name: ");
            stu.setName(sc.next());
            try {
                System.out.print("Enter age: ");
                stu.setAge(sc.nextInt());
            }catch(NumberFormatException e){
                System.out.println("Invalid input.");
                continue;
            }
            System.out.print("Enter from: ");
            stu.setFrom(sc.next());
            list.add(stu);
            System.out.println("Add studentInfo successfully");
            flag = false;            <=============相当于c语言的flag = 0,合法时输入才能结束
        }
    }
public static void signIn(ArrayList<User> list) {
        Scanner sc = new Scanner(System.in);
        System.out.println("Enter username: ");
        String username = sc.next();

        for (int i = 0; i < list.size(); i++) {
            if (list.get(i).getUsername().equals(username)) {
                boolean flag = true;               <============== 设置变量,相当于c语言的flag = 1
                loop:                                  <--------------- 同上
                while (flag) {                     <============== 同上
                    System.out.println("Enter 1 to input password, 2 to find password.");
                    String choice = sc.next();
                    if (choice.equals("1")) {
                        System.out.println("Enter password: ");
                        String password = sc.next();

                        if (list.get(i).getPassword().equals(password)) {
                            System.out.printf("Welcome %s\n", username);
                            Test_in.main(null);
                        } else {
                            System.out.println("Invalid password.");
                            continue;
                        }

                        flag = false;                     <============== 同上
                    } else if (choice.equals("2")) {
                        System.out.println("Enter id: ");
                        String id = sc.next();

                        System.out.println("Enter phone number: ");
                        String phoneNum = sc.next();

                        if (list.get(i).getId().equals(id) && list.get(i).getPhoneNum().equals(phoneNum)) {
                            System.out.println("Have sent your verification code.");
                            System.out.println("Enter verification code: ");
                            //TODO: send verification code
                            String code = Code.createCode();
                            System.out.printf("Your verification code is %s\n", code);
                            if (sc.next().equals(code)) {
                                System.out.println("Please enter your new password");
                                boolean flag2 = true;                           <=========== flag的多层嵌套
                                while (flag2) {                        <============== 同上
                                    System.out.println("Enter password: ");
                                    list.get(i).setPassword(sc.next());
                                    System.out.println("Enter password again: ");
                                    String password = sc.next();
                                    if (!list.get(i).getPassword().equals(password)) {
                                        System.out.println("password not same");
                                        System.out.println("Please enter again");
                                        continue;
                                    }
                                    flag2 = false;                                <============== 同上
                                    System.out.println("Please sign in again.");
                                    continue loop;                               <------------------- 同上
                                }
                            }
                        }else{
                            System.out.println("id or phone number is not valid");
                            System.out.println("Please enter again");
                        }

                    } else {
                        System.out.println("Please enter a valid choice");
                    }
                }
            }
        }
        System.out.println("No user");
    }

下面这位才是多级嵌套(屎山)

public static void register(ArrayList<User> list) {
        User user = new User();

        Scanner sc = new Scanner(System.in);

        boolean flag = true;                             <============== 同上
        loop:                                                        <------------------ 同上
        while (flag) {                                             <============== 同上
            boolean flag5 = true;                           <============== 同上
            while(flag5){                                          <============== 同上
                System.out.println("Enter username: ");
                user.setUsername(sc.next());
                if(user.getUsername().length()>10){
                    System.out.println("username is too long");
                    System.out.println("Please enter again");
                }else{
                    flag5 = false;                                  <============== 同上
                }
            }
            boolean flag2 = true;                                  <============== 同上
            while (flag2) {                                               <============== 同上
                System.out.println("Enter password: ");
                user.setPassword(sc.next());
                System.out.println("Enter password again: ");
                String password = sc.next();
                if (!user.getPassword().equals(password)) {
                    System.out.println("password not same");
                    System.out.println("Please enter again");
                    continue;
                }
                flag2 = false;                                                <============== 同上
            }

            for (int i = 0; i < list.size(); i++) {
                if (list.get(i).getUsername().equals(user.getUsername())) {
                    System.out.println("username already exists"); // 用户名重复,重新输入
                    continue loop;                                  <-------------------- 同上
                }
            }

            boolean flag3 = true;                            <============== 同上
            while(flag3){                                          <============== 同上
                System.out.println("Enter phone number: ");
                String phoneNum = sc.next();
                if(phoneNum.length()!=11||!isNumber(phoneNum,11)){
                    System.out.println("phone number is not valid");
                    System.out.println("Please enter again");
                }else{
                    flag3 = false;                                   <============== 同上
                    user.setPhoneNum(phoneNum);
                    boolean flag4 = true;                        <============== 同上
                    while(flag4){                                      <============== 同上
                        System.out.println("Enter id: ");
                        String id = sc.next();
                        if(id.length()!=18||!isNumber(id,17)){
                            if(id.charAt(18)!='x'||id.charAt(18)!='X'||id.charAt(18)>'9'||id.charAt(18)<'0'){
                                System.out.println("id is not valid");
                                System.out.println("Please enter again");
                            }
                        }else{
                            flag4 = false;                                    <============== 同上
                            user.setId(id);
                            System.out.println("register successfully");
                        }
                    }
                }
            }

            list.add(user);
            System.out.println("register successfully");
            flag = false;                                      <============== 同上
        }
    }

当然实际开发不会这样写,但是这是练习代码,我学习路上的拉的,这里主要讲的是循环的灵活运用。

希望对你有用
END

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值